diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java
index b6cdb7329..9aa621e14 100644
--- a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java
+++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java
@@ -114,4 +114,11 @@ public interface AuthServiceApi {
*/
void checkAuth(String token, String requestUrl);
+ /**
+ * 取消冻结帐号
+ *
+ * @author xixiaowei
+ * @date 2022/1/22 16:37
+ */
+ void cancelFreeze(LoginRequest loginRequest);
}
diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/constants/LoginCacheConstants.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/constants/LoginCacheConstants.java
new file mode 100644
index 000000000..5ab8cfaf1
--- /dev/null
+++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/constants/LoginCacheConstants.java
@@ -0,0 +1,25 @@
+package cn.stylefeng.roses.kernel.auth.api.constants;
+
+/**
+ * 登录前缀相关的常量
+ *
+ * @author xixiaowei
+ * @date 2022/1/22 17:37
+ */
+public interface LoginCacheConstants {
+
+ /**
+ * 登录最大次数
+ */
+ Integer MAX_LOGIN_COUNT = 5;
+
+ /**
+ * 登录冻结缓存前缀
+ */
+ String LOGIN_CACHE_PREFIX = "login:";
+
+ /**
+ * 冻结时间
+ */
+ Long LOGIN_CACHE_TIMEOUT_SECONDS = 1800L;
+}
diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/exception/enums/AuthExceptionEnum.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/exception/enums/AuthExceptionEnum.java
index ac449cee8..22b60362b 100644
--- a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/exception/enums/AuthExceptionEnum.java
+++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/exception/enums/AuthExceptionEnum.java
@@ -121,7 +121,12 @@ public enum AuthExceptionEnum implements AbstractExceptionEnum {
/**
* 无法访问未经授权的接口
*/
- CANT_REQUEST_UN_OPEN_API(RuleConstants.BUSINESS_ERROR_TYPE_CODE + AuthConstants.AUTH_EXCEPTION_STEP_CODE + "17", "无法访问未经授权的接口,未授权url为:{}");
+ CANT_REQUEST_UN_OPEN_API(RuleConstants.BUSINESS_ERROR_TYPE_CODE + AuthConstants.AUTH_EXCEPTION_STEP_CODE + "17", "无法访问未经授权的接口,未授权url为:{}"),
+
+ /**
+ * 超过最大登录次数
+ */
+ EXCEED_MAX_LOGIN_COUNT(RuleConstants.BUSINESS_ERROR_TYPE_CODE + AuthConstants.AUTH_EXCEPTION_STEP_CODE + "18", "超过最大登录次数,帐号被锁定");
/**
* 错误编码
diff --git a/kernel-d-auth/auth-sdk/pom.xml b/kernel-d-auth/auth-sdk/pom.xml
index 853b42278..c98b881c7 100644
--- a/kernel-d-auth/auth-sdk/pom.xml
+++ b/kernel-d-auth/auth-sdk/pom.xml
@@ -126,6 +126,11 @@
${roses.version}
+
+ cn.stylefeng.roses
+ system-business-user
+ ${roses.version}
+
diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java
index e0938cc9b..1c10fbad0 100644
--- a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java
+++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java
@@ -24,6 +24,7 @@
*/
package cn.stylefeng.roses.kernel.auth.auth;
+import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.CharsetUtil;
@@ -36,6 +37,7 @@ import cn.hutool.http.HttpResponse;
import cn.stylefeng.roses.kernel.auth.api.AuthServiceApi;
import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi;
import cn.stylefeng.roses.kernel.auth.api.constants.AuthConstants;
+import cn.stylefeng.roses.kernel.auth.api.constants.LoginCacheConstants;
import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
import cn.stylefeng.roses.kernel.auth.api.exception.AuthException;
import cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum;
@@ -47,6 +49,9 @@ import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginRequest;
import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginResponse;
import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginWithTokenRequest;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser;
+import cn.stylefeng.roses.kernel.auth.session.cache.loginuser.RedisLoginUserCache;
+import cn.stylefeng.roses.kernel.cache.api.CacheOperatorApi;
+import cn.stylefeng.roses.kernel.cache.memory.operator.DefaultMemoryCacheOperator;
import cn.stylefeng.roses.kernel.demo.expander.DemoConfigExpander;
import cn.stylefeng.roses.kernel.jwt.JwtTokenOperator;
import cn.stylefeng.roses.kernel.jwt.api.context.JwtContext;
@@ -66,10 +71,13 @@ import cn.stylefeng.roses.kernel.system.api.ResourceServiceApi;
import cn.stylefeng.roses.kernel.system.api.UserServiceApi;
import cn.stylefeng.roses.kernel.system.api.enums.UserStatusEnum;
import cn.stylefeng.roses.kernel.system.api.pojo.user.UserLoginInfoDTO;
+import cn.stylefeng.roses.kernel.system.modular.user.entity.SysUser;
+import cn.stylefeng.roses.kernel.system.modular.user.service.SysUserService;
import cn.stylefeng.roses.kernel.validator.api.exception.enums.ValidatorExceptionEnum;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Claims;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@@ -119,6 +127,15 @@ public class AuthServiceImpl implements AuthServiceApi {
@Resource
private ResourceServiceApi resourceServiceApi;
+ @Resource
+ private SysUserService sysUserService;
+
+ @Resource
+ private CacheOperatorApi loginCacheOperatorApi;
+
+ @Value("${login.enable}")
+ private Boolean enable;
+
@Override
public LoginResponse login(LoginRequest loginRequest) {
return loginAction(loginRequest, true, null);
@@ -254,6 +271,25 @@ public class AuthServiceImpl implements AuthServiceApi {
* @date 2020/10/21 16:59
*/
private LoginResponse loginAction(LoginRequest loginRequest, Boolean validatePassword, String caToken) {
+ SysUser userByAccount = sysUserService.getUserByAccount(loginRequest.getAccount());
+ // 判断登录错误检测是否开启
+ if (enable) {
+ // 判断错误次数,超过最大放入缓存中
+ if (StrUtil.isBlank(loginCacheOperatorApi.get(userByAccount.getUserId().toString()))) {
+ if (userByAccount.getLoginCount() > LoginCacheConstants.MAX_LOGIN_COUNT) {
+ loginCacheOperatorApi.put(userByAccount.getUserId().toString(), "true", 1800L);
+ throw new AuthException(AuthExceptionEnum.EXCEED_MAX_LOGIN_COUNT);
+ }
+ } else {
+ throw new AuthException(AuthExceptionEnum.EXCEED_MAX_LOGIN_COUNT);
+ }
+ }
+
+ // 5. 获取用户密码的加密值和用户的状态
+ UserLoginInfoDTO userValidateInfo = userServiceApi.getUserLoginInfo(loginRequest.getAccount());
+
+ // 8. 获取LoginUser,用于用户的缓存
+ LoginUser loginUser = userValidateInfo.getLoginUser();
// 1.参数为空校验
if (validatePassword) {
@@ -275,6 +311,8 @@ public class AuthServiceImpl implements AuthServiceApi {
throw new AuthException(ValidatorExceptionEnum.CAPTCHA_EMPTY);
}
if (!captchaApi.validateCaptcha(verKey, verCode)) {
+ // 登录失败日志
+ loginLogServiceApi.loginFail(loginUser.getUserId(), "验证码错误");
throw new AuthException(ValidatorExceptionEnum.CAPTCHA_ERROR);
}
}
@@ -288,6 +326,8 @@ public class AuthServiceImpl implements AuthServiceApi {
throw new AuthException(ValidatorExceptionEnum.CAPTCHA_EMPTY);
}
if (!dragCaptchaApi.validateCaptcha(verKey, Convert.toInt(verXLocationValue))) {
+ // 登录失败日志
+ loginLogServiceApi.loginFail(loginUser.getUserId(), "拖拽验证码错误");
throw new AuthException(ValidatorExceptionEnum.DRAG_CAPTCHA_ERROR);
}
}
@@ -308,13 +348,15 @@ public class AuthServiceImpl implements AuthServiceApi {
return new LoginResponse(remoteLoginCode);
}
- // 5. 获取用户密码的加密值和用户的状态
- UserLoginInfoDTO userValidateInfo = userServiceApi.getUserLoginInfo(loginRequest.getAccount());
-
// 6. 校验用户密码是否正确
if (validatePassword) {
Boolean checkResult = passwordStoredEncryptApi.checkPassword(loginRequest.getPassword(), userValidateInfo.getUserPasswordHexed());
if (!checkResult) {
+ //更新登录次数
+ userByAccount.setLoginCount(userByAccount.getLoginCount() + 1);
+ sysUserService.updateById(userByAccount);
+ // 登录失败日志
+ loginLogServiceApi.loginFail(loginUser.getUserId(), "帐号或密码错误");
throw new AuthException(AuthExceptionEnum.USERNAME_PASSWORD_ERROR);
}
}
@@ -324,9 +366,6 @@ public class AuthServiceImpl implements AuthServiceApi {
throw new AuthException(AuthExceptionEnum.USER_STATUS_ERROR, UserStatusEnum.getCodeMessage(userValidateInfo.getUserStatus()));
}
- // 8. 获取LoginUser,用于用户的缓存
- LoginUser loginUser = userValidateInfo.getLoginUser();
-
// 9. 生成用户的token
DefaultJwtPayload defaultJwtPayload = new DefaultJwtPayload(loginUser.getUserId(), loginUser.getAccount(), loginRequest.getRememberMe(), caToken);
String jwtToken = JwtContext.me().generateTokenDefaultPayload(defaultJwtPayload);
@@ -355,6 +394,10 @@ public class AuthServiceImpl implements AuthServiceApi {
String ip = HttpServletUtil.getRequestClientIp(HttpServletUtil.getRequest());
userServiceApi.updateUserLoginInfo(loginUser.getUserId(), new Date(), ip);
+ //重置登录次数
+ userByAccount.setLoginCount(1);
+ sysUserService.updateById(userByAccount);
+
// 13.登录成功日志
loginLogServiceApi.loginSuccess(loginUser.getUserId());
}
@@ -403,4 +446,13 @@ public class AuthServiceImpl implements AuthServiceApi {
return loginCode;
}
+ @Override
+ public void cancelFreeze(LoginRequest loginRequest) {
+ SysUser sysUser = sysUserService.getUserByAccount(loginRequest.getAccount());
+ sysUser.setLoginCount(1);
+ // 修改数据库中的登录次数
+ sysUserService.updateById(sysUser);
+ // 删除缓存中的数据
+ loginCacheOperatorApi.remove(sysUser.getUserId().toString());
+ }
}
diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/cache/LoginMemoryCache.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/cache/LoginMemoryCache.java
new file mode 100644
index 000000000..f4a891061
--- /dev/null
+++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/cache/LoginMemoryCache.java
@@ -0,0 +1,23 @@
+package cn.stylefeng.roses.kernel.auth.cache;
+
+import cn.hutool.cache.impl.TimedCache;
+import cn.stylefeng.roses.kernel.auth.api.constants.LoginCacheConstants;
+import cn.stylefeng.roses.kernel.cache.memory.AbstractMemoryCacheOperator;
+
+/**
+ * 用户帐号冻结的缓存
+ *
+ * @author xixiaowei
+ * @date 2022/1/22 17:33
+ */
+public class LoginMemoryCache extends AbstractMemoryCacheOperator {
+
+ public LoginMemoryCache(TimedCache timedCache) {
+ super(timedCache);
+ }
+
+ @Override
+ public String getCommonKeyPrefix() {
+ return LoginCacheConstants.LOGIN_CACHE_PREFIX;
+ }
+}
diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/cache/LoginRedisCache.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/cache/LoginRedisCache.java
new file mode 100644
index 000000000..07539c61e
--- /dev/null
+++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/cache/LoginRedisCache.java
@@ -0,0 +1,23 @@
+package cn.stylefeng.roses.kernel.auth.cache;
+
+import cn.stylefeng.roses.kernel.auth.api.constants.LoginCacheConstants;
+import cn.stylefeng.roses.kernel.cache.redis.AbstractRedisCacheOperator;
+import org.springframework.data.redis.core.RedisTemplate;
+
+/**
+ * 用户帐号冻结的缓存
+ *
+ * @author xixiaowei
+ * @date 2022/1/23 23:34
+ */
+public class LoginRedisCache extends AbstractRedisCacheOperator {
+
+ public LoginRedisCache(RedisTemplate redisTemplate) {
+ super(redisTemplate);
+ }
+
+ @Override
+ public String getCommonKeyPrefix() {
+ return LoginCacheConstants.LOGIN_CACHE_PREFIX;
+ }
+}
diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/config/AccountErrorDetectionConfig.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/config/AccountErrorDetectionConfig.java
new file mode 100644
index 000000000..cc8d63ea7
--- /dev/null
+++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/config/AccountErrorDetectionConfig.java
@@ -0,0 +1,22 @@
+package cn.stylefeng.roses.kernel.auth.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 控制帐号错误检测开关
+ *
+ * @author xixiaowei
+ * @date 2022/1/23 23:42
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "login")
+public class AccountErrorDetectionConfig {
+
+ /**
+ * 开关:true-开启错误检测,false-关闭错误检测
+ */
+ private Boolean enable;
+}
diff --git a/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/GunsLoginCacheAutoConfiguration.java b/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/GunsLoginCacheAutoConfiguration.java
new file mode 100644
index 000000000..ea3e2035c
--- /dev/null
+++ b/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/GunsLoginCacheAutoConfiguration.java
@@ -0,0 +1,33 @@
+package cn.stylefeng.roses.kernel.auth.starter;
+
+import cn.hutool.cache.CacheUtil;
+import cn.hutool.cache.impl.TimedCache;
+import cn.stylefeng.roses.kernel.auth.api.constants.LoginCacheConstants;
+import cn.stylefeng.roses.kernel.auth.cache.LoginMemoryCache;
+import cn.stylefeng.roses.kernel.cache.api.CacheOperatorApi;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 登录缓存的自动配置
+ *
+ * @author xixiaowei
+ * @date 2022/1/22 17:40
+ */
+@Configuration
+public class GunsLoginCacheAutoConfiguration {
+
+ /**
+ * 登录帐号冻结的缓存
+ *
+ * @author xixiaowei
+ * @date 2022/1/22 17:45
+ */
+ @Bean
+ @ConditionalOnMissingBean(name = "loginCacheOperatorApi")
+ public CacheOperatorApi loginCacheOperatorApi() {
+ TimedCache loginTimeCache = CacheUtil.newTimedCache(LoginCacheConstants.LOGIN_CACHE_TIMEOUT_SECONDS * 1000);
+ return new LoginMemoryCache(loginTimeCache);
+ }
+}
diff --git a/kernel-d-auth/auth-spring-boot-starter/src/main/resources/META-INF/spring.factories b/kernel-d-auth/auth-spring-boot-starter/src/main/resources/META-INF/spring.factories
index b97464eef..27e18f974 100644
--- a/kernel-d-auth/auth-spring-boot-starter/src/main/resources/META-INF/spring.factories
+++ b/kernel-d-auth/auth-spring-boot-starter/src/main/resources/META-INF/spring.factories
@@ -1,3 +1,4 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.stylefeng.roses.kernel.auth.starter.GunsAuthAutoConfiguration,\
- cn.stylefeng.roses.kernel.auth.starter.GunsSsoAutoConfiguration
\ No newline at end of file
+ cn.stylefeng.roses.kernel.auth.starter.GunsSsoAutoConfiguration,\
+ cn.stylefeng.roses.kernel.auth.starter.GunsLoginCacheAutoConfiguration
\ No newline at end of file
diff --git a/kernel-d-db/db-spring-boot-starter/pom.xml b/kernel-d-db/db-spring-boot-starter/pom.xml
index b0f12032c..851f11cc0 100644
--- a/kernel-d-db/db-spring-boot-starter/pom.xml
+++ b/kernel-d-db/db-spring-boot-starter/pom.xml
@@ -38,6 +38,11 @@
${roses.version}
+
+ com.alibaba
+ druid-spring-boot-starter
+ 1.2.8
+
diff --git a/kernel-d-db/db-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/db/starter/RemoveDruidAdConfig.java b/kernel-d-db/db-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/db/starter/RemoveDruidAdConfig.java
new file mode 100644
index 000000000..1128773b0
--- /dev/null
+++ b/kernel-d-db/db-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/db/starter/RemoveDruidAdConfig.java
@@ -0,0 +1,68 @@
+package cn.stylefeng.roses.kernel.db.starter;
+
+import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
+import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
+import com.alibaba.druid.util.Utils;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.servlet.*;
+import java.io.IOException;
+
+@Configuration
+@ConditionalOnWebApplication
+@AutoConfigureAfter(DruidDataSourceAutoConfigure.class)
+@ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true", matchIfMissing = true)
+public class RemoveDruidAdConfig {
+
+
+ /**
+ * 方法名: removeDruidAdFilterRegistrationBean
+ * 方法描述: 除去页面底部的广告
+ * @param properties
+ * @return org.springframework.boot.web.servlet.FilterRegistrationBean
+ * @throws
+ */
+ @Bean
+ public FilterRegistrationBean removeDruidAdFilterRegistrationBean(DruidStatProperties properties) {
+ // 获取web监控页面的参数
+ DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
+ // 提取common.js的配置路径
+ String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
+ String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
+
+ final String filePath = "support/http/resources/js/common.js";
+
+ //创建filter进行过滤
+ Filter filter = new Filter() {
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+ chain.doFilter(request, response);
+ // 重置缓冲区,响应头不会被重置
+ response.resetBuffer();
+ // 获取common.js
+ String text = Utils.readFromResource(filePath);
+ // 正则替换banner, 除去底部的广告信息
+ text = text.replaceAll("
", "");
+ text = text.replaceAll("powered.*?shrek.wang", "");
+ response.getWriter().write(text);
+ }
+
+ @Override
+ public void destroy() {
+ }
+ };
+ FilterRegistrationBean registrationBean = new FilterRegistrationBean();
+ registrationBean.setFilter(filter);
+ registrationBean.addUrlPatterns(commonJsPattern);
+ return registrationBean;
+ }
+}
\ No newline at end of file
diff --git a/kernel-s-system/system-business-user/pom.xml b/kernel-s-system/system-business-user/pom.xml
index 2e47dbeaa..3ff479793 100644
--- a/kernel-s-system/system-business-user/pom.xml
+++ b/kernel-s-system/system-business-user/pom.xml
@@ -114,11 +114,11 @@
-
- cn.stylefeng.roses
- auth-sdk
- ${roses.version}
-
+
+
+
+
+
@@ -126,6 +126,20 @@
spring-boot-starter-web
+
+
+ cn.stylefeng.roses
+ jwt-api
+ 7.1.6
+
+
+
+
+ cn.stylefeng.roses
+ message-api
+ 7.1.6
+
+
diff --git a/kernel-s-system/system-business-user/src/main/java/cn/stylefeng/roses/kernel/system/modular/user/controller/LoginController.java b/kernel-s-system/system-business-user/src/main/java/cn/stylefeng/roses/kernel/system/modular/user/controller/LoginController.java
index 8e7b58a4b..57ffd8fc9 100644
--- a/kernel-s-system/system-business-user/src/main/java/cn/stylefeng/roses/kernel/system/modular/user/controller/LoginController.java
+++ b/kernel-s-system/system-business-user/src/main/java/cn/stylefeng/roses/kernel/system/modular/user/controller/LoginController.java
@@ -143,4 +143,15 @@ public class LoginController {
return new SuccessResponseData<>(haveSessionFlag);
}
+ /**
+ * 取消帐号冻结
+ *
+ * @author xixiaowei
+ * @date 2022/1/22 16:40
+ */
+ @PostResource(name = "取消帐号冻结", path = "/cancelFreeze")
+ public ResponseData> cancelFreeze(@RequestBody LoginRequest loginRequest) {
+ authServiceApi.cancelFreeze(loginRequest);
+ return new SuccessResponseData<>();
+ }
}
diff --git a/kernel-s-system/system-business-user/src/main/java/cn/stylefeng/roses/kernel/system/modular/user/entity/SysUser.java b/kernel-s-system/system-business-user/src/main/java/cn/stylefeng/roses/kernel/system/modular/user/entity/SysUser.java
index ee0430b18..d32e1ebc8 100644
--- a/kernel-s-system/system-business-user/src/main/java/cn/stylefeng/roses/kernel/system/modular/user/entity/SysUser.java
+++ b/kernel-s-system/system-business-user/src/main/java/cn/stylefeng/roses/kernel/system/modular/user/entity/SysUser.java
@@ -154,4 +154,9 @@ public class SysUser extends BaseEntity {
@TableField(value = "del_flag", fill = FieldFill.INSERT)
private String delFlag;
+ /**
+ * 登录次数
+ */
+ @TableField("login_count")
+ private Integer loginCount;
}