yq %!s(int64=3) %!d(string=hai) anos
pai
achega
233f0d2f76

+ 2 - 0
src/main/java/com/usky/dxtop/common/constant/UserConstants.java

@@ -75,4 +75,6 @@ public class UserConstants
      */
     public static final int PASSWORD_MIN_LENGTH = 5;
     public static final int PASSWORD_MAX_LENGTH = 20;
+
+    public static final String ACCOUNT_LOCK = "lock_account_";
 }

+ 68 - 0
src/main/java/com/usky/dxtop/controller/web/business/AccountLockController.java

@@ -0,0 +1,68 @@
+package com.usky.dxtop.controller.web.business;
+
+
+
+import com.usky.dxtop.common.core.domain.ApiResult;
+import com.usky.dxtop.common.core.page.CommonPage;
+import com.usky.dxtop.model.AccountLock;
+import com.usky.dxtop.service.AccountLockService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 账号登录限制
+ * @author ya
+ * @since 2022-04-06
+ */
+@RestController
+@RequestMapping("/accountLock")
+public class AccountLockController {
+
+    @Autowired
+    private AccountLockService accountLockService;
+    /**
+     * 新增记录
+     * @param accountLock
+     * @return
+     */
+    @PostMapping
+    public ApiResult<Boolean> add(@RequestBody AccountLock accountLock){
+        return ApiResult.success(accountLockService.add(accountLock));
+    }
+
+    /**
+     * 修改记录
+     * @return
+     */
+    @PutMapping
+    public ApiResult<Boolean> update(@RequestBody AccountLock accountLock){
+        return ApiResult.success(accountLockService.update(accountLock));
+    }
+
+    /**
+     * 删除记录
+     * @param id
+     * @return
+     */
+    @DeleteMapping("/{id}")
+    public ApiResult<Boolean> delete(@PathVariable("id") Long id){
+        return ApiResult.success(accountLockService.delete(id));
+    }
+
+    /**
+     * 记录查询
+     * @param current 页数
+     * @param size 条数
+     * @param name 名称
+     * @return
+     */
+    @GetMapping("list")
+    public ApiResult<CommonPage<AccountLock>> page(@RequestParam Integer current,
+                                                   @RequestParam Integer size,
+                                                   @RequestParam(required = false) String name){
+        return ApiResult.success(accountLockService.page(current,size,name));
+    }
+
+
+}
+

+ 14 - 1
src/main/java/com/usky/dxtop/controller/web/system/SysUserController.java

@@ -9,8 +9,10 @@ import com.usky.dxtop.common.exception.CustomException;
 import com.usky.dxtop.common.utils.SecurityUtils;
 import com.usky.dxtop.common.utils.StringUtils;
 import com.usky.dxtop.controller.BaseController;
+import com.usky.dxtop.model.AccountLock;
 import com.usky.dxtop.model.SysRole;
 import com.usky.dxtop.model.SysUser;
+import com.usky.dxtop.service.AccountLockService;
 import com.usky.dxtop.service.ISysPostService;
 import com.usky.dxtop.service.ISysRoleService;
 import com.usky.dxtop.service.ISysUserService;
@@ -43,7 +45,8 @@ public class SysUserController extends BaseController
 
     @Autowired
     private ISysPostService postService;
-
+    @Autowired
+    private AccountLockService accountLockService;
     /**
      * 获取用户列表
      */
@@ -98,6 +101,7 @@ public class SysUserController extends BaseController
         {
             throw new CustomException("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
         }
+        checkAccount(user);
         user.setCreateBy(SecurityUtils.getUsername());
         user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
         return toAjax(userService.insertUser(user));
@@ -190,4 +194,13 @@ public class SysUserController extends BaseController
         userService.insertUserAuth(userId, roleIds);
         return success();
     }
+
+    public void checkAccount(SysUser sysUser){
+        AccountLock accountLock = accountLockService.isEnableOne();
+        if (null != accountLock){
+            if (sysUser.getPassword().length() < accountLock.getPwdLength()){
+                throw new CustomException("密码长度不能低于"+accountLock.getPwdLength()+"位");
+            }
+        }
+    }
 }

+ 47 - 1
src/main/java/com/usky/dxtop/framework/web/service/SysLoginService.java

@@ -1,6 +1,7 @@
 package com.usky.dxtop.framework.web.service;
 
 import com.usky.dxtop.common.constant.Constants;
+import com.usky.dxtop.common.constant.UserConstants;
 import com.usky.dxtop.common.core.domain.model.LoginUser;
 import com.usky.dxtop.common.core.redis.RedisCache;
 import com.usky.dxtop.common.exception.CustomException;
@@ -13,9 +14,12 @@ import com.usky.dxtop.common.utils.ServletUtils;
 import com.usky.dxtop.common.utils.ip.IpUtils;
 import com.usky.dxtop.framework.manager.AsyncManager;
 import com.usky.dxtop.framework.manager.factory.AsyncFactory;
+import com.usky.dxtop.model.AccountLock;
 import com.usky.dxtop.model.SysUser;
+import com.usky.dxtop.service.AccountLockService;
 import com.usky.dxtop.service.ISysConfigService;
 import com.usky.dxtop.service.ISysUserService;
+import com.usky.dxtop.service.vo.UserAccountVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.BadCredentialsException;
@@ -24,6 +28,8 @@ import org.springframework.security.core.Authentication;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
 
 
 /**
@@ -49,6 +55,8 @@ public class SysLoginService
     @Autowired
     private ISysConfigService configService;
 
+    @Autowired
+    private AccountLockService accountLockService;
     /**
      * 登录验证
      * 
@@ -81,7 +89,7 @@ public class SysLoginService
             if (e instanceof BadCredentialsException)
             {
                 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
-                throw new UserPasswordNotMatchException();
+                lockAccount(username);
             }
             else
             {
@@ -130,4 +138,42 @@ public class SysLoginService
         user.setLoginDate(DateUtils.getNowDate());
         userService.updateUserProfile(user);
     }
+
+
+    /**
+     * 锁定账号
+     * @param userName
+     */
+    public void lockAccount(String userName){
+        AccountLock accountLock = accountLockService.isEnableOne();
+        if (null != accountLock){
+            Object cacheObj = redisCache.getCacheObject(getLockAccountKey(userName));
+            if (Objects.nonNull(cacheObj))
+            {
+                UserAccountVO userAccountVO = (UserAccountVO) cacheObj;
+                userAccountVO.setUseCount(userAccountVO.getUseCount()+1);
+                int i = userAccountVO.getTotalCount() - userAccountVO.getUseCount();
+                if (userAccountVO.getTotalCount() > userAccountVO.getUseCount()){
+                    redisCache.setCacheObject(getLockAccountKey(userName),userAccountVO);
+                    throw new CustomException("密码输入错误还剩下"+i+"次机会");
+                } else {
+                    redisCache.setCacheObject(getLockAccountKey(userName),userAccountVO,accountLock.getLoseDate(), TimeUnit.MINUTES);
+                    throw new CustomException(userAccountVO.getTotalCount()+"次机会已经用完,账号被锁定"+accountLock.getLoseDate()+"分钟");
+                }
+            }else {
+                UserAccountVO userAccountVO = new UserAccountVO();
+                userAccountVO.setTotalCount(accountLock.getLockNumber());
+                userAccountVO.setUseCount(1);
+                redisCache.setCacheObject(getLockAccountKey(userName),userAccountVO);
+                int i = userAccountVO.getTotalCount() - 1;
+                throw new CustomException("密码输入错误还剩下"+i+"次机会");
+            }
+        }else {
+            throw new CustomException("密码输入不正确");
+        }
+    }
+
+    public String getLockAccountKey(String userName){
+        return UserConstants.ACCOUNT_LOCK + "_" + userName;
+    }
 }

+ 17 - 0
src/main/java/com/usky/dxtop/mapper/AccountLockMapper.java

@@ -0,0 +1,17 @@
+package com.usky.dxtop.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.usky.dxtop.model.AccountLock;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author ya
+ * @since 2022-04-06
+ */
+public interface AccountLockMapper extends BaseMapper<AccountLock> {
+
+}

+ 74 - 0
src/main/java/com/usky/dxtop/model/AccountLock.java

@@ -0,0 +1,74 @@
+package com.usky.dxtop.model;
+
+import java.time.LocalDateTime;
+import java.io.Serializable;
+import java.util.Date;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author ya
+ * @since 2022-04-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class AccountLock implements Serializable {
+
+    private static final long serialVersionUID=1L;
+
+    /**
+     * 主键
+     */
+    private Long id;
+    /**
+     * 名称
+     */
+    private String name;
+
+    /**
+     * 密码长度
+     */
+    private Integer pwdLength;
+
+    /**
+     * 失效时间
+     */
+    private Integer loseDate;
+
+    /**
+     * 锁定次数
+     */
+    private Integer lockNumber;
+
+    /**
+     * 是否默认
+     */
+    private Boolean isEnable;
+    /**
+     * 创建人
+     */
+    private String createBy;
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+    /**
+     * 修改时间
+     */
+    private Date updateTime;
+    /**
+     * 修改人
+     */
+    private Date updateBy;
+
+
+    private Boolean delFlag;
+
+}

+ 59 - 0
src/main/java/com/usky/dxtop/service/AccountLockService.java

@@ -0,0 +1,59 @@
+package com.usky.dxtop.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.usky.dxtop.common.core.page.CommonPage;
+import com.usky.dxtop.model.AccountLock;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author ya
+ * @since 2022-04-06
+ */
+public interface AccountLockService extends IService<AccountLock> {
+    /**
+     * add
+     * @param accountLock
+     * @return
+     */
+    Boolean add(AccountLock accountLock);
+
+    /**
+     * update
+     * @return
+     */
+    Boolean update(AccountLock accountLock);
+
+    Boolean checkNameUnique(AccountLock accountLock);
+
+    /**
+     * 删除
+     * @param id
+     * @return
+     */
+    Boolean delete(Long id);
+
+    /**
+     * 建筑查询
+     * @param name
+     * @param current
+     * @param size
+     * @return
+     */
+    CommonPage<AccountLock> page(Integer current, Integer size, String name);
+
+    /**
+     * 查看默认开启的权限
+     * @return
+     */
+    AccountLock isEnableOne();
+
+    /**
+     * 修改默认权限
+     * @return
+     */
+    Boolean updateEnable();
+}

+ 110 - 0
src/main/java/com/usky/dxtop/service/impl/AccountLockServiceImpl.java

@@ -0,0 +1,110 @@
+package com.usky.dxtop.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.usky.dxtop.common.core.page.CommonPage;
+import com.usky.dxtop.common.exception.CustomException;
+import com.usky.dxtop.common.utils.SecurityUtils;
+import com.usky.dxtop.common.utils.StringUtils;
+import com.usky.dxtop.mapper.AccountLockMapper;
+import com.usky.dxtop.model.AccountLock;
+import com.usky.dxtop.service.AccountLockService;
+import org.springframework.stereotype.Service;
+
+import java.util.Objects;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author ya
+ * @since 2022-04-06
+ */
+@Service
+public class AccountLockServiceImpl extends ServiceImpl<AccountLockMapper, AccountLock> implements AccountLockService {
+
+    @Override
+    public Boolean add(AccountLock accountLock) {
+        accountLock.setCreateBy(SecurityUtils.getUsername());
+        if (checkNameUnique(accountLock)){
+            throw new CustomException("名称不能重复");
+        }
+        if (null != accountLock.getIsEnable() && accountLock.getIsEnable()){
+            updateEnable();
+        }
+        return this.save(accountLock);
+    }
+
+    @Override
+    public Boolean update(AccountLock accountLock) {
+        if (checkNameUnique(accountLock)){
+            throw new CustomException("名称不能重复");
+        }
+        if (null != accountLock.getIsEnable() && accountLock.getIsEnable()){
+            updateEnable();
+        }
+        return this.updateById(accountLock);
+    }
+
+    @Override
+    public Boolean checkNameUnique(AccountLock accountLock) {
+        Long id =  null == accountLock.getId() ? -1 : accountLock.getId();
+        LambdaQueryWrapper<AccountLock> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(AccountLock::getName,accountLock.getName())
+                .eq(AccountLock::getDelFlag,false);
+        AccountLock one = this.getOne(queryWrapper);
+        if (Objects.nonNull(one) && one.getId() != id.longValue())
+        {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean delete(Long id) {
+        AccountLock byId = this.getById(id);
+        if (byId.getIsEnable()){
+            throw new CustomException("默认开关已打开,关闭后再删除");
+        }
+        AccountLock accountLock = new AccountLock();
+        accountLock.setId(id);
+        accountLock.setDelFlag(true);
+        return this.updateById(accountLock);
+    }
+
+    @Override
+    public CommonPage<AccountLock> page(Integer current, Integer size, String name) {
+        IPage<AccountLock> page = new Page<>(current, size);
+        LambdaQueryWrapper<AccountLock> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper
+                .like(StringUtils.isNotBlank(name),AccountLock::getName,name)
+                .eq(AccountLock::getDelFlag,false)
+                .orderByDesc(AccountLock::getId);
+        page =  this.page(page,queryWrapper);
+        return new CommonPage<>(page.getRecords(),page.getTotal(),page.getSize(),page.getCurrent());
+    }
+
+    @Override
+    public AccountLock isEnableOne() {
+        LambdaQueryWrapper<AccountLock> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper
+                .eq(AccountLock::getIsEnable,true)
+                .eq(AccountLock::getDelFlag,false);
+        return this.getOne(queryWrapper);
+    }
+
+    @Override
+    public Boolean updateEnable() {
+        AccountLock enableOne = isEnableOne();
+        if (null != enableOne){
+            enableOne.setIsEnable(false);
+            this.updateById(enableOne);
+        }
+        return true;
+    }
+}

+ 17 - 0
src/main/java/com/usky/dxtop/service/vo/UserAccountVO.java

@@ -0,0 +1,17 @@
+package com.usky.dxtop.service.vo;
+
+import lombok.Data;
+
+@Data
+public class UserAccountVO {
+
+
+    /**
+     * 总数
+     */
+    private Integer totalCount;
+    /**
+     * 已使用数
+     */
+    private Integer useCount;
+}

+ 18 - 0
src/main/resources/mapper/AccountLockMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.usky.dxtop.mapper.AccountLockMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.usky.dxtop.model.AccountLock">
+        <id column="id" property="id" />
+        <result column="pwd_length" property="pwdLength" />
+        <result column="lose_date" property="loseDate" />
+        <result column="lock_number" property="lockNumber" />
+        <result column="is_enable" property="isEnable" />
+        <result column="create_by" property="createBy" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="update_by" property="updateBy" />
+    </resultMap>
+
+</mapper>