diff --git a/blade-auth/src/main/java/org/springblade/auth/service/BladeUserDetailsServiceImpl.java b/blade-auth/src/main/java/org/springblade/auth/service/BladeUserDetailsServiceImpl.java index db106977..b9e500ac 100644 --- a/blade-auth/src/main/java/org/springblade/auth/service/BladeUserDetailsServiceImpl.java +++ b/blade-auth/src/main/java/org/springblade/auth/service/BladeUserDetailsServiceImpl.java @@ -21,11 +21,10 @@ import lombok.SneakyThrows; import org.apache.commons.lang.StringUtils; import org.springblade.auth.constant.AuthConstant; import org.springblade.auth.utils.TokenUtil; +import org.springblade.common.cache.CacheNames; +import org.springblade.core.redis.cache.BladeRedis; import org.springblade.core.tool.api.R; -import org.springblade.core.tool.utils.Func; -import org.springblade.core.tool.utils.StringPool; -import org.springblade.core.tool.utils.StringUtil; -import org.springblade.core.tool.utils.WebUtil; +import org.springblade.core.tool.utils.*; import org.springblade.system.entity.Tenant; import org.springblade.system.feign.ISysClient; import org.springblade.system.user.entity.User; @@ -39,6 +38,7 @@ import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthoriza import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; +import java.time.Duration; /** * 用户信息 @@ -49,9 +49,13 @@ import javax.servlet.http.HttpServletRequest; @AllArgsConstructor public class BladeUserDetailsServiceImpl implements UserDetailsService { + public static final Integer FAIL_COUNT = 5; + private final IUserClient userClient; private final ISysClient sysClient; + private final BladeRedis bladeRedis; + @Override @SneakyThrows public BladeUserDetails loadUserByUsername(String username) { @@ -59,11 +63,19 @@ public class BladeUserDetailsServiceImpl implements UserDetailsService { // 获取租户ID String headerTenant = request.getHeader(TokenUtil.TENANT_HEADER_KEY); String paramTenant = request.getParameter(TokenUtil.TENANT_PARAM_KEY); + String password = request.getParameter(TokenUtil.PASSWORD_KEY); if (StringUtil.isAllBlank(headerTenant, paramTenant)) { throw new UserDeniedAuthorizationException(TokenUtil.TENANT_NOT_FOUND); } String tenantId = StringUtils.isBlank(headerTenant) ? paramTenant : headerTenant; + // 判断登录是否锁定 + // TODO 2.8.3版本将增加:1.参数管理读取配置 2.用户管理增加解封按钮 + int cnt = Func.toInt(bladeRedis.get(CacheNames.tenantKey(tenantId, CacheNames.USER_FAIL_KEY, username)), 0); + if (cnt >= FAIL_COUNT) { + throw new UserDeniedAuthorizationException(TokenUtil.USER_HAS_TOO_MANY_FAILS); + } + // 获取租户信息 R tenant = sysClient.getTenant(tenantId); if (tenant.isSuccess()) { @@ -92,7 +104,9 @@ public class BladeUserDetailsServiceImpl implements UserDetailsService { if (result.isSuccess()) { UserInfo userInfo = result.getData(); User user = userInfo.getUser(); - if (user == null || user.getId() == null) { + if (user == null || user.getId() == null || !user.getPassword().equals(DigestUtil.hex(password))) { + // 错误次数锁定 + bladeRedis.setEx(CacheNames.tenantKey(tenantId, CacheNames.USER_FAIL_KEY, username), cnt + 1, Duration.ofMinutes(30)); throw new UsernameNotFoundException(TokenUtil.USER_NOT_FOUND); } if (Func.isEmpty(userInfo.getRoles())) { diff --git a/blade-auth/src/main/java/org/springblade/auth/utils/TokenUtil.java b/blade-auth/src/main/java/org/springblade/auth/utils/TokenUtil.java index febe8066..fc15b7e4 100644 --- a/blade-auth/src/main/java/org/springblade/auth/utils/TokenUtil.java +++ b/blade-auth/src/main/java/org/springblade/auth/utils/TokenUtil.java @@ -69,9 +69,11 @@ public class TokenUtil { public final static String USER_HAS_NO_ROLE = "未获得用户的角色信息"; public final static String USER_HAS_NO_TENANT = "未获得用户的租户信息"; public final static String USER_HAS_NO_TENANT_PERMISSION = "租户授权已过期,请联系管理员"; + public final static String USER_HAS_TOO_MANY_FAILS = "登录错误次数过多,请稍后再试"; public final static String HEADER_KEY = "Authorization"; public final static String HEADER_PREFIX = "Basic "; public final static String DEFAULT_AVATAR = ""; + public final static String PASSWORD_KEY = "password"; private static BladeTenantProperties tenantProperties; diff --git a/blade-common/src/main/java/org/springblade/common/cache/CacheNames.java b/blade-common/src/main/java/org/springblade/common/cache/CacheNames.java index c033ca9b..90355cd0 100644 --- a/blade-common/src/main/java/org/springblade/common/cache/CacheNames.java +++ b/blade-common/src/main/java/org/springblade/common/cache/CacheNames.java @@ -23,6 +23,37 @@ package org.springblade.common.cache; */ public interface CacheNames { + /** + * 返回拼接后的key + * + * @param cacheKey 缓存key + * @param cacheKeyValue 缓存key值 + * @return tenantKey + */ + static String cacheKey(String cacheKey, String cacheKeyValue) { + return cacheKey.concat(cacheKeyValue); + } + + /** + * 返回租户格式的key + * + * @param tenantId 租户编号 + * @param cacheKey 缓存key + * @param cacheKeyValue 缓存key值 + * @return tenantKey + */ + static String tenantKey(String tenantId, String cacheKey, String cacheKeyValue) { + return tenantId.concat(":").concat(cacheKey).concat(cacheKeyValue); + } + + /** + * 验证码key + */ String CAPTCHA_KEY = "blade:auth::blade:captcha:"; + /** + * 登录失败key + */ + String USER_FAIL_KEY = "blade:user::blade:fail:"; + }