Ver código fonte

feat: login error lock 10m

shc 11 meses atrás
pai
commit
f1d9a353fd

+ 53 - 29
hnqz-auth/src/main/java/com/qunzhixinxi/hnqz/auth/handler/HnqzAuthenticationFailureEventHandler.java

@@ -1,4 +1,3 @@
-
 package com.qunzhixinxi.hnqz.auth.handler;
 
 import com.qunzhixinxi.hnqz.admin.api.entity.SysLog;
@@ -11,6 +10,7 @@ import com.qunzhixinxi.hnqz.common.security.handler.AuthenticationFailureHandler
 import lombok.AllArgsConstructor;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.http.HttpHeaders;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.security.core.Authentication;
@@ -19,6 +19,7 @@ import org.springframework.stereotype.Component;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.util.concurrent.TimeUnit;
 
 /**
  * @author hnqz
@@ -29,33 +30,56 @@ import javax.servlet.http.HttpServletResponse;
 @AllArgsConstructor
 public class HnqzAuthenticationFailureEventHandler implements AuthenticationFailureHandler {
 
-	private final RemoteLogService logService;
-
-	/**
-	 * 异步处理,登录失败方法
-	 * <p>
-	 * @param authenticationException 登录的authentication 对象
-	 * @param authentication 登录的authenticationException 对象
-	 * @param request 请求
-	 * @param response 响应
-	 */
-	@Async
-	@Override
-	@SneakyThrows
-	public void handle(AuthenticationException authenticationException, Authentication authentication,
-			HttpServletRequest request, HttpServletResponse response) {
-		String username = authentication.getName();
-		SysLog sysLog = SysLogUtils.getSysLog(request, username);
-		sysLog.setTitle(username + "用户登录");
-		sysLog.setType(CommonConstants.STATUS_LOCK);
-		sysLog.setParams(username);
-		sysLog.setException(authenticationException.getLocalizedMessage());
-		String header = request.getHeader(HttpHeaders.AUTHORIZATION);
-		sysLog.setServiceId(WebUtils.extractClientId(header).orElse("N/A"));
-
-		logService.saveLog(sysLog, SecurityConstants.FROM_IN);
-
-		log.info("用户:{} 登录失败,异常:{}", username, authenticationException.getLocalizedMessage());
-	}
+    private final RemoteLogService logService;
+    private final RedisTemplate<String, Object> redisTemplate;
+
+    /**
+     * 异步处理,登录失败方法
+     * <p>
+     *
+     * @param authenticationException 登录的authentication 对象
+     * @param authentication          登录的authenticationException 对象
+     * @param request                 请求
+     * @param response                响应
+     */
+    @Async
+    @Override
+    @SneakyThrows
+    public void handle(AuthenticationException authenticationException, Authentication authentication,
+                       HttpServletRequest request, HttpServletResponse response) {
+        String username = authentication.getName();
+        SysLog sysLog = SysLogUtils.getSysLog(request, username);
+        sysLog.setTitle(username + "用户登录");
+        sysLog.setType(CommonConstants.STATUS_LOCK);
+        sysLog.setParams(username);
+        sysLog.setException(authenticationException.getLocalizedMessage());
+        String header = request.getHeader(HttpHeaders.AUTHORIZATION);
+        sysLog.setServiceId(WebUtils.extractClientId(header).orElse("N/A"));
+
+        logService.saveLog(sysLog, SecurityConstants.FROM_IN);
+
+        log.info("用户:{} 登录失败,异常:{}", username, authenticationException.getLocalizedMessage());
+
+        // 连续失败5次锁定10分钟
+
+        final String errorKey = "login:error:lock:" + username;
+        final String lockKey = "login:error:limit:times:" + username;
+
+        if (Boolean.TRUE.equals(redisTemplate.hasKey("lockKey"))) {
+            Object o = redisTemplate.opsForValue().get(lockKey);
+            int limit = Integer.parseInt(o.toString());
+
+            if (limit >= 5) {
+                redisTemplate.opsForValue().set(errorKey, username, 10, TimeUnit.MINUTES);
+            } else {
+                redisTemplate.opsForValue().increment(lockKey, 1);
+            }
+
+
+        } else {
+            redisTemplate.opsForValue().set(lockKey, 1);
+        }
+
+    }
 
 }

+ 8 - 5
hnqz-auth/src/main/java/com/qunzhixinxi/hnqz/auth/handler/HnqzAuthenticationSuccessEventHandler.java

@@ -1,4 +1,3 @@
-
 package com.qunzhixinxi.hnqz.auth.handler;
 
 import com.qunzhixinxi.hnqz.admin.api.entity.SysLog;
@@ -9,6 +8,7 @@ import com.qunzhixinxi.hnqz.common.log.util.SysLogUtils;
 import com.qunzhixinxi.hnqz.common.security.handler.AuthenticationSuccessHandler;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.http.HttpHeaders;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.security.core.Authentication;
@@ -17,16 +17,13 @@ import org.springframework.stereotype.Component;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-/**
- * @author hnqz
- * @date 2018/10/8
- */
 @Slf4j
 @Component
 @AllArgsConstructor
 public class HnqzAuthenticationSuccessEventHandler implements AuthenticationSuccessHandler {
 
 	private final RemoteLogService logService;
+	private final RedisTemplate<String, Object> redisTemplate;
 
 	/**
 	 * 处理登录成功方法
@@ -48,6 +45,12 @@ public class HnqzAuthenticationSuccessEventHandler implements AuthenticationSucc
 
 		logService.saveLog(sysLog, SecurityConstants.FROM_IN);
 		log.info("用户:{} 登录成功", username);
+
+		// 登陆成功后删除错误次数
+		final String lockKey = "login:error:limit:times:" + username;
+
+		redisTemplate.delete(lockKey);
+
 	}
 
 }

+ 3 - 0
hnqz-auth/src/main/java/com/qunzhixinxi/hnqz/auth/service/HnqzUserDetailsServiceImpl.java

@@ -16,6 +16,7 @@ import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.cache.Cache;
 import org.springframework.cache.CacheManager;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.core.userdetails.UserDetails;
@@ -41,6 +42,7 @@ public class HnqzUserDetailsServiceImpl implements HnqzUserDetailsService {
 
     private final CacheManager cacheManager;
 
+
     /**
      * 用户密码登录
      *
@@ -64,6 +66,7 @@ public class HnqzUserDetailsServiceImpl implements HnqzUserDetailsService {
         }
 
 
+
         Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS);
         if (cache != null && cache.get(rawUsername) != null) {
             return (HnqzUser) cache.get(rawUsername).get();

+ 71 - 71
hnqz-common/hnqz-common-core/src/main/java/com/qunzhixinxi/hnqz/common/core/constant/CacheConstants.java

@@ -8,76 +8,76 @@ package com.qunzhixinxi.hnqz.common.core.constant;
  */
 public interface CacheConstants {
 
-	/**
-	 * 全局缓存,在缓存名称上加上该前缀表示该缓存不区分租户,比如:
-	 * <p/>
-	 * {@code @Cacheable(value = CacheConstants.GLOBALLY+CacheConstants.MENU_DETAILS, key = "#roleId  + '_menu'", unless = "#result == null")}
-	 */
-	String GLOBALLY = "gl:";
-
-	/**
-	 * 验证码前缀
-	 */
-	String DEFAULT_CODE_KEY = "DEFAULT_CODE_KEY:";
-
-	/**
-	 * 菜单信息缓存
-	 */
-	String MENU_DETAILS = "menu_details";
-
-	/**
-	 * 用户信息缓存
-	 */
-	String USER_DETAILS = "user_details";
-
-	/**
-	 * 字典信息缓存
-	 */
-	String DICT_DETAILS = "dict_details";
-
-	/**
-	 * oauth 客户端信息
-	 */
-	String CLIENT_DETAILS_KEY = "hnqz_oauth:client:details";
-
-	/**
-	 * spring boot admin 事件key
-	 */
-	String EVENT_KEY = "event_key";
-
-	/**
-	 * 路由存放
-	 */
-	String ROUTE_KEY = "gateway_route_key";
-
-	/**
-	 * redis reload 事件
-	 */
-	String ROUTE_REDIS_RELOAD_TOPIC = "gateway_redis_route_reload_topic";
-
-	/**
-	 * 内存reload 时间
-	 */
-	String ROUTE_JVM_RELOAD_TOPIC = "gateway_jvm_route_reload_topic";
-
-	/**
-	 * 公众号 reload
-	 */
-	String MP_REDIS_RELOAD_TOPIC = "mp_redis_reload_topic";
-
-	/**
-	 * 支付 reload 事件
-	 */
-	String PAY_REDIS_RELOAD_TOPIC = "pay_redis_reload_topic";
-
-	/**
-	 * 参数缓存
-	 */
-	String PARAMS_DETAILS = "params_details";
-
-	/**
-	 * 租户缓存 (不区分租户)
-	 */
-	String TENANT_DETAILS = GLOBALLY + "tenant_details";
+    /**
+     * 全局缓存,在缓存名称上加上该前缀表示该缓存不区分租户,比如:
+     * <p/>
+     * {@code @Cacheable(value = CacheConstants.GLOBALLY+CacheConstants.MENU_DETAILS, key = "#roleId  + '_menu'", unless = "#result == null")}
+     */
+    String GLOBALLY = "gl:";
+
+    /**
+     * 验证码前缀
+     */
+    String DEFAULT_CODE_KEY = "DEFAULT_CODE_KEY:";
+
+    /**
+     * 菜单信息缓存
+     */
+    String MENU_DETAILS = "menu_details";
+
+    /**
+     * 用户信息缓存
+     */
+    String USER_DETAILS = "user_details";
+
+    /**
+     * 字典信息缓存
+     */
+    String DICT_DETAILS = "dict_details";
+
+    /**
+     * oauth 客户端信息
+     */
+    String CLIENT_DETAILS_KEY = "hnqz_oauth:client:details";
+
+    /**
+     * spring boot admin 事件key
+     */
+    String EVENT_KEY = "event_key";
+
+    /**
+     * 路由存放
+     */
+    String ROUTE_KEY = "gateway_route_key";
+
+    /**
+     * redis reload 事件
+     */
+    String ROUTE_REDIS_RELOAD_TOPIC = "gateway_redis_route_reload_topic";
+
+    /**
+     * 内存reload 时间
+     */
+    String ROUTE_JVM_RELOAD_TOPIC = "gateway_jvm_route_reload_topic";
+
+    /**
+     * 公众号 reload
+     */
+    String MP_REDIS_RELOAD_TOPIC = "mp_redis_reload_topic";
+
+    /**
+     * 支付 reload 事件
+     */
+    String PAY_REDIS_RELOAD_TOPIC = "pay_redis_reload_topic";
+
+    /**
+     * 参数缓存
+     */
+    String PARAMS_DETAILS = "params_details";
+
+    /**
+     * 租户缓存 (不区分租户)
+     */
+    String TENANT_DETAILS = GLOBALLY + "tenant_details";
 
 }

+ 6 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/impl/SysUserServiceImpl.java

@@ -629,6 +629,12 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
      */
     @Override
     public UserInfo findUserInfo(SysUser sysUser) {
+
+        final String errorKey = "login:error:lock:" + sysUser.getUsername();
+        if (Boolean.TRUE.equals(redisTemplate.hasKey(errorKey))){
+            sysUser.setLockFlag(CommonConstants.STATUS_LOCK);
+        }
+
         UserInfo userInfo = new UserInfo();
         userInfo.setSysUser(sysUser);
         // 设置角色列表 (ID)