用户登录问题修改

This commit is contained in:
jiang 2024-10-29 14:17:22 +08:00
parent 48d410a8b7
commit 1c04ab1602
27 changed files with 572 additions and 153 deletions

View File

@ -19,11 +19,11 @@ import com.bonus.system.api.model.LoginUser;
* @author bonus
*/
@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteUserService
{
public interface RemoteUserService {
/**
* 根据条件如用户名手机号码状态停用或正常和创建时间获取当前登录用户数据权限范围内的用户信息
*
* @param user 角色信息
* @param source 请求来源使用SecurityConstants.INNER
* @return 满足条件的用户信息分页信息
@ -42,6 +42,27 @@ public interface RemoteUserService
@GetMapping("/user/info/{username}")
public R<LoginUser> getUserInfo(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 通过用户名查询用户信息
*
* @param phone 手机号
* @param source 请求来源
* @return 结果
*/
@GetMapping("/user//infoPhoto/{phone}")
public R<LoginUser> getUserInfoByPhone(@PathVariable("phone") String phone, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 通过用户名查询用户信息
*
* @param email 邮箱
* @param source 请求来源
* @return 结果
*/
@GetMapping("/user/infoEmail/{email}")
public R<LoginUser> getUserInfoByEmail(@PathVariable("email") String email, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 注册用户信息
*
@ -54,6 +75,7 @@ public interface RemoteUserService
/**
* 获取当前登录用户权限内的角色和权限集合
*
* @param source 请求来源
* @return 用户信息
*/
@ -62,6 +84,7 @@ public interface RemoteUserService
/**
* 根据用户编号获取详细信息,用户权限内的角色和权限集合
*
* @param userId 用户id
* @param source 请求来源
* @return 用户信息
@ -77,6 +100,7 @@ public interface RemoteUserService
/**
* 修改用户
*
* @param user 修改用户的用户信息
* @param source 请求来源
* @return 修改用户影响的行数或错误信息
@ -86,6 +110,7 @@ public interface RemoteUserService
/**
* 删除用户
*
* @param userIds 删除用户id列表
* @param source 请求来源
* @return 删除用户影响的行数或错误信息
@ -95,6 +120,7 @@ public interface RemoteUserService
/**
* 状态修改
*
* @param user 修改用户的信息
* @param source 请求来源
* @return 修改用户状态的影响的行数或错误信息
@ -104,6 +130,7 @@ public interface RemoteUserService
/**
* 根据用户编号获取授权角色信息
*
* @param userId 用户id
* @param source 请求来源
* @return 用户角色信息
@ -113,16 +140,18 @@ public interface RemoteUserService
/**
* 给定用户id给用户授权角色
*
* @param userId 用户id
* @param roleIds 授权角色id列表
* @param source 请求来源
* @return 成功授权消息或失败消息
*/
@PutMapping("/user/authRole")
public AjaxResult insertAuthRole(@PathVariable("userId")Long userId, @PathVariable("roleIds")Long[] roleIds, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
public AjaxResult insertAuthRole(@PathVariable("userId") Long userId, @PathVariable("roleIds") Long[] roleIds, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 获取当前登录用户数据权限范围内的部门权限下的部门树列表
*
* @param dept 部门信息
* @param source 请求来源
* @return 部门树列表或失败消息
@ -132,6 +161,7 @@ public interface RemoteUserService
/**
* 获取当前登录用户数据权限范围内的部门权限下的部门人员树列表
*
* @param dept 部门信息
* @param source 请求来源
* @return 部门人员树列表或失败消息
@ -141,6 +171,7 @@ public interface RemoteUserService
/**
* 修改用户审批状态
*
* @param user 用户信息
* @param source 请求来源
* @return 部门树列表或失败消息

View File

@ -44,6 +44,30 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
return R.fail("获取用户失败:" + throwable.getMessage());
}
/**
* 通过用户名查询用户信息
*
* @param phone 手机号
* @param source 请求来源
* @return 结果
*/
@Override
public R<LoginUser> getUserInfoByPhone(String phone, String source) {
return R.fail("获取用户失败:" + throwable.getMessage());
}
/**
* 通过用户名查询用户信息
*
* @param email 邮箱
* @param source 请求来源
* @return 结果
*/
@Override
public R<LoginUser> getUserInfoByEmail(String email, String source) {
return R.fail("获取用户失败:" + throwable.getMessage());
}
@Override
public R<Boolean> registerUserInfo(SysUser sysUser, String source)
{

View File

@ -84,6 +84,12 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-common-config</artifactId>
<version>24.10.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@ -0,0 +1,35 @@
package com.bonus.auth.controller;
import com.bonus.common.core.domain.R;
import com.bonus.config.SystemConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
/**
* @author bonus 系统配置层
*/
@RestController
@Slf4j
@RefreshScope
public class ConfigController {
@Resource
private SystemConfig systemConfig;
@GetMapping("getConfig")
public R<Object> getConfig() {
Map<String, Object> map = new HashMap<>();
map.put("loginConfig", systemConfig.getLoginConfig());
map.put("registersConfig", systemConfig.getRegistersConfig());
map.put("isAdmin", systemConfig.isAdmin());
map.put("isAddRootCompany",systemConfig.isAddRootCompany());
map.put("requestConfig",systemConfig.getRequestConfig());
map.put("passwordConfig",systemConfig.getPasswordConfig());
return R.ok(map);
}
}

View File

@ -14,12 +14,12 @@ import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.security.auth.AuthUtil;
import com.bonus.common.security.service.TokenService;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.config.SystemConfig;
import com.bonus.system.api.RemoteUserService;
import com.bonus.system.api.domain.SysUser;
import com.bonus.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -37,8 +37,8 @@ import java.util.Set;
@Slf4j
public class TokenController {
@Value("${isAdmin}")
private boolean isAdmin;
@Resource
private SystemConfig config;
@Autowired
private TokenService tokenService;
@ -60,7 +60,7 @@ public class TokenController {
@PostMapping("isAdmin")
public R<?> isAdmin(@RequestBody LoginBody form) {
if (!isAdmin) {
if (!config.isAdmin()) {
return R.ok(false);
}
passwordValidatorService.validateLoginParameters(form.getUsername(), form.getPassword());

View File

@ -2,6 +2,8 @@ package com.bonus.auth.service;
import com.bonus.common.core.constant.SecurityConstants;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.config.SystemConfig;
import com.bonus.system.api.RemoteUserService;
import com.bonus.system.api.domain.SysUser;
import com.bonus.system.api.model.LoginUser;
@ -14,6 +16,8 @@ import javax.annotation.Resource;
*/
@Service
public class EmailOtpLoginStrategy implements LoginStrategy {
@Resource
private SystemConfig systemConfig;
@Resource
private RemoteUserService remoteUserService;
@ -22,7 +26,10 @@ public class EmailOtpLoginStrategy implements LoginStrategy {
@Override
public LoginUser login(String email, String otp) {
R<LoginUser> userResult = remoteUserService.getUserInfo(email, SecurityConstants.INNER);
if (!systemConfig.getLoginConfig().isPhoneCode()) {
throw new ServiceException("用户不存在/密码错误");
}
R<LoginUser> userResult = remoteUserService.getUserInfoByEmail(email, SecurityConstants.INNER);
LoginUser userInfo = userResult.getData();
SysUser user = userInfo.getSysUser();
//验证用户是否存在

View File

@ -2,6 +2,8 @@ package com.bonus.auth.service;
import com.bonus.common.core.constant.SecurityConstants;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.config.SystemConfig;
import com.bonus.system.api.RemoteUserService;
import com.bonus.system.api.domain.SysUser;
import com.bonus.system.api.model.LoginUser;
@ -14,6 +16,9 @@ import javax.annotation.Resource;
*/
@Service
public class EmailPasswordLoginStrategy implements LoginStrategy {
@Resource
private SystemConfig systemConfig;
@Resource
private RemoteUserService remoteUserService;
@ -24,8 +29,11 @@ public class EmailPasswordLoginStrategy implements LoginStrategy {
@Override
public LoginUser login(String email, String password) {
if (!systemConfig.getLoginConfig().isEmailPassword()) {
throw new ServiceException("用户不存在/密码错误");
}
//通过手机号获取用户信息
R<LoginUser> userResult = remoteUserService.getUserInfo(email, SecurityConstants.INNER);
R<LoginUser> userResult = remoteUserService.getUserInfoByEmail(email, SecurityConstants.INNER);
//验证用户是否存在
passwordValidatorService.validateUserResult(email, userResult);
//获取用户信息

View File

@ -1,6 +1,5 @@
package com.bonus.auth.service;
import com.bonus.auth.config.PasswordPolicyConfig;
import com.bonus.common.core.constant.CacheConstants;
import com.bonus.common.core.constant.UserConstants;
import com.bonus.common.core.domain.R;
@ -12,6 +11,7 @@ import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.utils.ip.IpUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.redis.service.RedisService;
import com.bonus.config.SystemConfig;
import com.bonus.system.api.domain.SysUser;
import com.bonus.system.api.model.LoginUser;
import org.springframework.stereotype.Component;
@ -23,7 +23,7 @@ import java.util.concurrent.TimeUnit;
public class PasswordValidatorService {
@Resource
private PasswordPolicyConfig config;
private SystemConfig systemConfig;
@Resource
private RedisService redisService;
@ -40,7 +40,7 @@ public class PasswordValidatorService {
*/
public AjaxResult validatePassword(String username, String newPassword) {
if (!isPasswordLengthValid(newPassword)) {
return AjaxResult.error("密码长度应为" + config.getMinLength() + "" + config.getMaxLength() + "位!");
return AjaxResult.error("密码长度应为" + systemConfig.getPasswordConfig().getMinLength() + "" + systemConfig.getPasswordConfig().getMaxLength() + "位!");
}
if (!containsRequiredCharacters(newPassword)) {
@ -51,8 +51,8 @@ public class PasswordValidatorService {
return AjaxResult.error("密码包含常见的弱密码片段!");
}
if (containsConsecutiveCharacters(newPassword.toLowerCase(), config.getMaxConsecutiveChars())) {
return AjaxResult.error("密码不能包含超过" + config.getMaxConsecutiveChars() + "个连续相同字符、连续递增/递减的数字或字母(不区分大小写)");
if (containsConsecutiveCharacters(newPassword.toLowerCase(), systemConfig.getPasswordConfig().getMaxConsecutiveChars())) {
return AjaxResult.error("密码不能包含超过" + systemConfig.getPasswordConfig().getMaxConsecutiveChars() + "个连续相同字符、连续递增/递减的数字或字母(不区分大小写)");
}
if (newPassword.toLowerCase().contains(username.toLowerCase())) {
@ -66,7 +66,7 @@ public class PasswordValidatorService {
* 检查密码长度是否符合配置要求
*/
private boolean isPasswordLengthValid(String password) {
return password.length() >= config.getMinLength() && password.length() <= config.getMaxLength();
return password.length() >= systemConfig.getPasswordConfig().getMinLength() && password.length() <= systemConfig.getPasswordConfig().getMaxLength();
}
/**
@ -90,26 +90,26 @@ public class PasswordValidatorService {
}
}
return (!config.isRequireUpperCase() || hasUpperCase) &&
(!config.isRequireLowerCase() || hasLowerCase) &&
(!config.isRequireDigit() || hasDigit) &&
(!config.isRequireSpecialChar() || hasSpecialChar);
return (!systemConfig.getPasswordConfig().isRequireUpperCase() || hasUpperCase) &&
(!systemConfig.getPasswordConfig().isRequireLowerCase() || hasLowerCase) &&
(!systemConfig.getPasswordConfig().isRequireDigit() || hasDigit) &&
(!systemConfig.getPasswordConfig().isRequireSpecialChar() || hasSpecialChar);
}
/**
* 根据配置返回密码不符合要求时的错误提示信息
*/
private String getCharacterRequirementErrorMessage() {
if (config.isRequireUpperCase()) {
if (systemConfig.getPasswordConfig().isRequireUpperCase()) {
return "密码必须包含大写字母!";
}
if (config.isRequireLowerCase()) {
if (systemConfig.getPasswordConfig().isRequireLowerCase()) {
return "密码必须包含小写字母!";
}
if (config.isRequireDigit()) {
if (systemConfig.getPasswordConfig().isRequireDigit()) {
return "密码必须包含数字!";
}
if (config.isRequireSpecialChar()) {
if (systemConfig.getPasswordConfig().isRequireSpecialChar()) {
return "密码必须包含特殊字符!";
}
return "密码不符合字符要求!";
@ -119,7 +119,7 @@ public class PasswordValidatorService {
* 检查密码是否包含常见的弱密码
*/
private boolean containsWeakPassword(String password) {
for (String weakPwd : config.getWeakPasswords()) {
for (String weakPwd : systemConfig.getPasswordConfig().getWeakPasswords()) {
if (password.toLowerCase().contains(weakPwd)) {
return true;
}

View File

@ -2,6 +2,8 @@ package com.bonus.auth.service;
import com.bonus.common.core.constant.SecurityConstants;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.config.SystemConfig;
import com.bonus.system.api.RemoteUserService;
import com.bonus.system.api.domain.SysUser;
import com.bonus.system.api.model.LoginUser;
@ -14,6 +16,9 @@ import javax.annotation.Resource;
*/
@Service
public class PhoneOtpLoginStrategy implements LoginStrategy {
@Resource
private SystemConfig systemConfig;
@Resource
private RemoteUserService remoteUserService;
@ -25,7 +30,10 @@ public class PhoneOtpLoginStrategy implements LoginStrategy {
@Override
public LoginUser login(String phone, String otp) {
R<LoginUser> userResult = remoteUserService.getUserInfo(phone, SecurityConstants.INNER);
if (!systemConfig.getLoginConfig().isPhoneCode()) {
throw new ServiceException("用户不存在/密码错误");
}
R<LoginUser> userResult = remoteUserService.getUserInfoByPhone(phone, SecurityConstants.INNER);
LoginUser userInfo = userResult.getData();
SysUser user = userInfo.getSysUser();
//验证用户是否存在

View File

@ -2,6 +2,8 @@ package com.bonus.auth.service;
import com.bonus.common.core.constant.SecurityConstants;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.config.SystemConfig;
import com.bonus.system.api.RemoteUserService;
import com.bonus.system.api.domain.SysUser;
import com.bonus.system.api.model.LoginUser;
@ -14,6 +16,10 @@ import javax.annotation.Resource;
*/
@Service
public class PhonePasswordLoginStrategy implements LoginStrategy {
@Resource
private SystemConfig systemConfig;
@Resource
private RemoteUserService remoteUserService;
@ -25,8 +31,11 @@ public class PhonePasswordLoginStrategy implements LoginStrategy {
@Override
public LoginUser login(String phone, String password) {
if (!systemConfig.getLoginConfig().isPhonePassword()) {
throw new ServiceException("用户不存在/密码错误");
}
//通过手机号获取用户信息
R<LoginUser> userResult = remoteUserService.getUserInfo(phone, SecurityConstants.INNER);
R<LoginUser> userResult = remoteUserService.getUserInfoByPhone(phone, SecurityConstants.INNER);
//验证用户是否存在
passwordValidatorService.validateUserResult(phone, userResult);
//获取用户信息

View File

@ -5,6 +5,7 @@ import com.bonus.common.core.domain.R;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.security.service.EmailService;
import com.bonus.common.security.service.SmsService;
import com.bonus.config.SystemConfig;
import com.bonus.system.api.RemoteUserService;
import com.bonus.system.api.model.LoginUser;
import org.springframework.stereotype.Service;
@ -24,6 +25,8 @@ public class RegisterVerificationCodeSender implements VerificationCodeStrategy
private EmailService emailService;
@Resource
private SmsService smsService;
@Resource
private SystemConfig systemConfig;
@Resource
private RemoteUserService remoteUserService;
@ -36,13 +39,23 @@ public class RegisterVerificationCodeSender implements VerificationCodeStrategy
*/
@Override
public String sendVerificationCode(String contactInfo) {
R<LoginUser> userResult = remoteUserService.getUserInfo(contactInfo, SecurityConstants.INNER);
if (isEmail(contactInfo)) {
if (!systemConfig.getRegistersConfig().isEmailRegisters()) {
throw new ServiceException("请输入正确的联系方式");
}
R<LoginUser> userResult = remoteUserService.getUserInfoByEmail(contactInfo, SecurityConstants.INNER);
if (userResult.getData() != null) {
throw new ServiceException("联系方式已经注册账号");
}
if (isEmail(contactInfo)) {
return emailService.sendSimpleEmail(contactInfo);
} else if (isPhone(contactInfo)) {
if (!systemConfig.getRegistersConfig().isPhoneRegisters()) {
throw new ServiceException("请输入正确的联系方式");
}
R<LoginUser> userResult = remoteUserService.getUserInfoByPhone(contactInfo, SecurityConstants.INNER);
if (userResult.getData() != null) {
throw new ServiceException("联系方式已经注册账号");
}
return smsService.sendSimplePhone(contactInfo);
} else {
throw new ServiceException("请输入正确的联系方式");

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.bonus</groupId>
<artifactId>bonus-common</artifactId>
<version>24.10.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>bonus-common-config</artifactId>
<description>
bonus-common-config系统配置模块
</description>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,157 @@
package com.bonus.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author bonus 系统配置
*/
@RefreshScope
@Component
@ConfigurationProperties(prefix = "system-config")
@Data
public class SystemConfig {
/**
* 登录配置
*/
private LoginConfig loginConfig;
/**
*增加配置以支持增加根节点公司的添加和删除功能
*/
private boolean isAddRootCompany;
/**
* token过期时间
*/
private Long tokenTime;
/**
* 是否是管理员登录
*/
private boolean isAdmin;
/**
* 注册配置
*/
private RegistersConfig registersConfig;
/**
* 网络请求
*/
private RequestConfig requestConfig;
/**
* 密码配置校验
*/
private PasswordConfig passwordConfig;
@Data
@RefreshScope
public static class LoginConfig {
/**
* 手机密码登录
*/
private boolean phonePassword;
/**
* 邮箱密码登录
*/
private boolean emailPassword;
/**
* 手机验证码
*/
private boolean phoneCode;
/**
* 邮箱验证码
*/
private boolean emailCode;
}
@Data
@RefreshScope
public static class RegistersConfig {
/**
* 手机注册
*/
private boolean phoneRegisters;
/**
* 邮箱注册
*/
private boolean emailRegisters;
}
@Data
@RefreshScope
public static class RequestConfig {
/**
* 请求加密
*/
private boolean encryptRequest;
/**
* 数据完整性校验
*/
private boolean checkIntegrity;
/**
* 返回数据加密
*/
private boolean encryptResponse;
}
@Data
@RefreshScope
public static class PasswordConfig{
/**
* 密码的最小长度
*/
private int minLength;
/**
* 密码的最大长度
*/
private int maxLength;
/**
* 是否需要包含大写字母
*/
private boolean requireUpperCase;
/**
* 是否需要包含小写字母
*/
private boolean requireLowerCase;
/**
* 是否需要包含数字
*/
private boolean requireDigit;
/**
* 是否需要包含特殊字符
*/
private boolean requireSpecialChar;
/**
* 常见的弱密码列表禁止使用这些密码
*/
private List<String> weakPasswords;
/**
* 密码历史记录限制
*/
private int passwordHistoryLimit;
/**
* 是否限制连续相同字符
*/
private boolean restrictConsecutiveChars;
/**
* 最大允许的连续字符数
*/
private int maxConsecutiveChars;
/**
* 密码中是否不能包含用户名
*/
private boolean excludeUsernameInPassword;
/**
* 是否在首次登录时强制修改密码
*/
private boolean forcePasswordChangeOnFirstLogin;
/**
*是否开启定期修改密码
*/
private boolean enableRegularlyChangePassword;
/**
* 定期修改密码天数
*/
private Integer regularlyChangePassword;
}
}

View File

@ -9,13 +9,14 @@ import com.bonus.common.core.utils.ip.IpUtils;
import com.bonus.common.core.utils.uuid.IdUtils;
import com.bonus.common.redis.service.RedisService;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.config.SystemConfig;
import com.bonus.system.api.model.LoginUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@ -28,8 +29,9 @@ import java.util.concurrent.TimeUnit;
*/
@Component
public class TokenService {
@Value("${tokenTime}")
private Long tokenTime;
@Resource
private SystemConfig systemConfig;
private static final Logger log = LoggerFactory.getLogger(TokenService.class);
@ -72,7 +74,7 @@ public class TokenService {
rspMap.put("access_token", accessToken);
rspMap.put("expires_in", EXPIRETIME);
//对token进行存储
redisService.setCacheObject(LOGIN_USER_KEY + userId, token, tokenTime, TimeUnit.MINUTES);
redisService.setCacheObject(LOGIN_USER_KEY + userId, token, systemConfig.getTokenTime(), TimeUnit.MINUTES);
return rspMap;
}
@ -174,10 +176,10 @@ public class TokenService {
*/
public void refreshToken(LoginUser loginUser) {
loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(loginUser.getLoginTime() + tokenTime * MILLIS_MINUTE);
loginUser.setExpireTime(loginUser.getLoginTime() + systemConfig.getTokenTime() * MILLIS_MINUTE);
// 根据uuid将loginUser缓存
String userKey = getTokenKey(loginUser.getToken());
redisService.setCacheObject(userKey, loginUser, tokenTime, TimeUnit.MINUTES);
redisService.setCacheObject(userKey, loginUser, systemConfig.getTokenTime(), TimeUnit.MINUTES);
}
private String getTokenKey(String token) {

View File

@ -18,6 +18,7 @@
<module>bonus-common-sensitive</module>
<module>bonus-common-datascope</module>
<module>bonus-common-datasource</module>
<module>bonus-common-config</module>
</modules>
<artifactId>bonus-common</artifactId>

View File

@ -97,6 +97,10 @@
<artifactId>knife4j-spring-ui</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-common-config</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -133,7 +133,6 @@ public class RequestCoverFilter implements GlobalFilter, Ordered {
ServerHttpRequest request = exchange.getRequest();
boolean integrality = "true".equalsIgnoreCase(request.getHeaders().getFirst(INTEGRALITY));
boolean encrypt = "true".equalsIgnoreCase(request.getHeaders().getFirst(ENCRYPT));
return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(dataBuffer -> {
byte[] body = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(body);

View File

@ -1,16 +1,15 @@
package com.bonus.gateway.handler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.support.NotFoundException;
import com.bonus.common.core.utils.ServletUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import com.bonus.common.core.utils.ServletUtils;
import reactor.core.publisher.Mono;
/**
@ -30,7 +29,7 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler
{
ServerHttpResponse response = exchange.getResponse();
if (exchange.getResponse().isCommitted())
if (response.isCommitted())
{
return Mono.error(ex);
}
@ -50,7 +49,7 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler
{
msg = "内部服务器错误";
}
System.err.println(ex.getMessage());
log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage());
return ServletUtils.webFluxResponseWriter(response, msg);

View File

@ -78,11 +78,13 @@
<artifactId>bonus-common-log</artifactId>
</dependency>
<!-- bonus Common Swagger -->
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-common-swagger</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>

View File

@ -59,12 +59,7 @@ public class SysUserController extends BaseController {
@Resource
private PasswordValidatorService passwordValidatorService;
// @Resource
// private RemoteFileService remoteFileService;
// @PostMapping("upload")
// public AjaxResult upload(MultipartFile file){
// return remoteFileService.upload(file);
// }
/**
* 获取用户列表
*/
@ -145,6 +140,48 @@ public class SysUserController extends BaseController {
}
/**
* 获取当前用户信息
*/
@InnerAuth
@GetMapping("/infoPhoto/{photoNumber}")
public R<LoginUser> infoPhotoNumber(@PathVariable("photoNumber") String photoNumber) {
SysUser sysUser = userService.selectUserByPhotoNumber(photoNumber);
if (StringUtils.isNull(sysUser)) {
return R.fail("用户名或密码错误");
}
// 角色集合
Set<String> roles = permissionService.getRolePermission(sysUser);
// 权限集合
Set<String> permissions = permissionService.getMenuPermission(sysUser);
LoginUser sysUserVo = new LoginUser();
sysUserVo.setSysUser(sysUser);
sysUserVo.setRoles(roles);
sysUserVo.setPermissions(permissions);
return R.ok(sysUserVo);
}
/**
* 获取当前用户信息
*/
@InnerAuth
@GetMapping("/infoEmail/{email}")
public R<LoginUser> infoEmail(@PathVariable("email") String email) {
SysUser sysUser = userService.selectUserByEmail(email);
if (StringUtils.isNull(sysUser)) {
return R.fail("用户名或密码错误");
}
// 角色集合
Set<String> roles = permissionService.getRolePermission(sysUser);
// 权限集合
Set<String> permissions = permissionService.getMenuPermission(sysUser);
LoginUser sysUserVo = new LoginUser();
sysUserVo.setSysUser(sysUser);
sysUserVo.setRoles(roles);
sysUserVo.setPermissions(permissions);
return R.ok(sysUserVo);
}
/**
* 注册用户信息
*/

View File

@ -3,8 +3,10 @@ package com.bonus.system.mapper;
import java.util.List;
import com.bonus.system.api.domain.SysDept;
import org.apache.ibatis.annotations.Param;
import com.bonus.system.api.domain.SysUser;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 用户表 数据层
@ -43,7 +45,25 @@ public interface SysUserMapper {
* @param userName 用户名
* @return 用户对象信息
*/
public SysUser selectUserByUserName(@Param("userName") String userName,@Param("loginType") String loginType);
public SysUser selectUserByUserName(@Param("userName") String userName);
/**
* 通过手机号查询用户
*
* @param phoneNumber 手机号
* @return 用户对象信息
*/
public SysUser selectUserByPhoneNumber(@Param("phoneNumber") String phoneNumber);
/**
* 通过邮箱查询用户
*
* @param email 邮箱
* @return 用户对象信息
*/
public SysUser selectUserByEmail(@Param("email") String email);
/**
* 通过用户ID查询用户
@ -143,4 +163,5 @@ public interface SysUserMapper {
* @return
*/
List<SysDept> getTree(SysDept dept);
}

View File

@ -1,18 +1,17 @@
package com.bonus.system.service;
import java.util.List;
import com.bonus.common.core.domain.R;
import com.bonus.system.api.domain.SysUser;
import org.apache.poi.ss.formula.functions.T;
import java.util.List;
/**
* 用户 业务层
*
* @author bonus
*/
public interface ISysUserService
{
public interface ISysUserService {
/**
* 根据条件分页查询用户列表
*
@ -45,6 +44,23 @@ public interface ISysUserService
*/
public SysUser selectUserByUserName(String userName);
/**
* 通过手机号查询用户
*
* @param photoNumber 用户名
* @return 用户对象信息
*/
public SysUser selectUserByPhotoNumber(String photoNumber);
/**
* 通过邮箱查询用户
*
* @param email 用户名
* @return 用户对象信息
*/
public SysUser selectUserByEmail(String email);
/**
* 通过用户ID查询用户
*

View File

@ -3,9 +3,9 @@ package com.bonus.system.service.impl;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.config.SystemConfig;
import com.bonus.system.api.domain.SysUser;
import com.bonus.system.api.model.LoginUser;
import com.bonus.system.config.PasswordPolicyConfig;
import com.bonus.system.domain.UserPasswordHistory;
import com.bonus.system.mapper.PasswordValidatorMapper;
import com.bonus.system.service.ISysConfigService;
@ -22,7 +22,7 @@ import java.util.Set;
public class PasswordValidatorServiceImpl implements PasswordValidatorService {
@Resource
private PasswordPolicyConfig config;
private SystemConfig systemConfig;
@Resource
private ISysConfigService configService;
@ -34,7 +34,7 @@ public class PasswordValidatorServiceImpl implements PasswordValidatorService {
public AjaxResult validatePassword(Long userId, String username, String oldPassword, String newPassword) {
// 1. 检查密码长度
if (!isPasswordLengthValid(newPassword)) {
return AjaxResult.error("密码长度应为" + config.getMinLength() + "" + config.getMaxLength() + "位!");
return AjaxResult.error("密码长度应为" + systemConfig.getPasswordConfig().getMinLength() + "" + systemConfig.getPasswordConfig().getMaxLength() + "位!");
}
// 2. 检查密码字符类型
@ -48,12 +48,12 @@ public class PasswordValidatorServiceImpl implements PasswordValidatorService {
}
// 4. 检查连续字符
if (config.isRestrictConsecutiveChars() && containsConsecutiveCharacters(newPassword.toLowerCase(), config.getMaxConsecutiveChars())) {
return AjaxResult.error("密码不能包含超过" + config.getMaxConsecutiveChars() + "位连续字符!");
if (systemConfig.getPasswordConfig().isRestrictConsecutiveChars() && containsConsecutiveCharacters(newPassword.toLowerCase(), systemConfig.getPasswordConfig().getMaxConsecutiveChars())) {
return AjaxResult.error("密码不能包含超过" + systemConfig.getPasswordConfig().getMaxConsecutiveChars() + "位连续字符!");
}
// 5. 检查用户名
if (config.isExcludeUsernameInPassword() && newPassword.toLowerCase().contains(username.toLowerCase())) {
if (systemConfig.getPasswordConfig().isExcludeUsernameInPassword() && newPassword.toLowerCase().contains(username.toLowerCase())) {
return AjaxResult.error("密码不能包含账号!");
}
@ -64,14 +64,14 @@ public class PasswordValidatorServiceImpl implements PasswordValidatorService {
// 7. 检查密码历史
if (isPasswordInHistory(userId, newPassword)) {
return AjaxResult.error("新密码不能与最近的" + config.getPasswordHistoryLimit() + "个旧密码相同!");
return AjaxResult.error("新密码不能与最近的" + systemConfig.getPasswordConfig().getPasswordHistoryLimit() + "个旧密码相同!");
}
return AjaxResult.success();
}
private boolean isPasswordLengthValid(String password) {
return password.length() >= config.getMinLength() && password.length() <= config.getMaxLength();
return password.length() >= systemConfig.getPasswordConfig().getMinLength() && password.length() <= systemConfig.getPasswordConfig().getMaxLength();
}
private boolean isPasswordCharacterValid(String password) {
@ -84,14 +84,14 @@ public class PasswordValidatorServiceImpl implements PasswordValidatorService {
if ("!@#$%^&*()-_=+[{]};:'\",<.>/?".indexOf(c) >= 0) hasSpecialChar = true;
}
if (config.isRequireUpperCase() && !hasUpperCase) return false;
if (config.isRequireLowerCase() && !hasLowerCase) return false;
if (config.isRequireDigit() && !hasDigit) return false;
return !(config.isRequireSpecialChar() && !hasSpecialChar);
if (systemConfig.getPasswordConfig().isRequireUpperCase() && !hasUpperCase) return false;
if (systemConfig.getPasswordConfig().isRequireLowerCase() && !hasLowerCase) return false;
if (systemConfig.getPasswordConfig().isRequireDigit() && !hasDigit) return false;
return !(systemConfig.getPasswordConfig().isRequireSpecialChar() && !hasSpecialChar);
}
private boolean containsWeakPassword(String password) {
Set<String> weakPasswords = new HashSet<>(config.getWeakPasswords());
Set<String> weakPasswords = new HashSet<>(systemConfig.getPasswordConfig().getWeakPasswords());
for (String weakPwd : weakPasswords) {
if (password.contains(weakPwd)) {
return true;
@ -104,16 +104,16 @@ public class PasswordValidatorServiceImpl implements PasswordValidatorService {
* 根据配置返回密码不符合要求时的错误提示信息
*/
private String getCharacterRequirementErrorMessage() {
if (config.isRequireUpperCase()) {
if (systemConfig.getPasswordConfig().isRequireUpperCase()) {
return "密码必须包含大写字母!";
}
if (config.isRequireLowerCase()) {
if (systemConfig.getPasswordConfig().isRequireLowerCase()) {
return "密码必须包含小写字母!";
}
if (config.isRequireDigit()) {
if (systemConfig.getPasswordConfig().isRequireDigit()) {
return "密码必须包含数字!";
}
if (config.isRequireSpecialChar()) {
if (systemConfig.getPasswordConfig().isRequireSpecialChar()) {
return "密码必须包含特殊字符!";
}
return "密码不符合字符要求!";
@ -124,7 +124,7 @@ public class PasswordValidatorServiceImpl implements PasswordValidatorService {
if (userPasswordHistories.isEmpty()) return false;
// 只取最近的五次修改记录
int limit = Math.min(userPasswordHistories.size(), config.getPasswordHistoryLimit());
int limit = Math.min(userPasswordHistories.size(), systemConfig.getPasswordConfig().getPasswordHistoryLimit());
for (int i = 0; i < limit; i++) {
UserPasswordHistory history = userPasswordHistories.get(i);
if (SecurityUtils.matchesPassword(newPassword, history.getNewPassword())) {
@ -136,7 +136,7 @@ public class PasswordValidatorServiceImpl implements PasswordValidatorService {
@Override
public boolean checkFirstLogin() {
if (!config.isForcePasswordChangeOnFirstLogin()) {
if (!systemConfig.getPasswordConfig().isForcePasswordChangeOnFirstLogin()) {
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
@ -147,6 +147,9 @@ public class PasswordValidatorServiceImpl implements PasswordValidatorService {
@Override
public boolean checkPasswordExpiry() {
if (!systemConfig.getPasswordConfig().isEnableRegularlyChangePassword()) {
return false;
}
Long userId = SecurityUtils.getUserId();
List<UserPasswordHistory> userPasswordHistories = passwordValidatorMapper.checkPasswordExpiry(userId);
if (userPasswordHistories.isEmpty()) {
@ -157,7 +160,7 @@ public class PasswordValidatorServiceImpl implements PasswordValidatorService {
Date changeDate = DateUtils.toDate(userPasswordHistory.getChangeTimestamp());
long daysSinceChange = DateUtils.daysBetween(changeDate, currentDate);
return daysSinceChange > config.getRegularlyChangePassword();
return daysSinceChange > systemConfig.getPasswordConfig().getRegularlyChangePassword();
}
@Override
@ -167,7 +170,7 @@ public class PasswordValidatorServiceImpl implements PasswordValidatorService {
return AjaxResult.success("没有找到密码历史记录。");
}
int limit = Math.min(userPasswordHistories.size(), config.getPasswordHistoryLimit());
int limit = Math.min(userPasswordHistories.size(), systemConfig.getPasswordConfig().getPasswordHistoryLimit());
for (int i = 0; i < limit; i++) {
UserPasswordHistory history = userPasswordHistories.get(i);
if (SecurityUtils.matchesPassword(newPassword, history.getNewPassword())) {

View File

@ -7,6 +7,7 @@ import com.bonus.common.core.utils.SpringUtils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.utils.bean.BeanValidators;
import com.bonus.common.core.utils.sms.SmsUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.core.web.domain.BaseEntity;
import com.bonus.common.datascope.annotation.DataScope;
import com.bonus.common.datascope.utils.CommonDataPermissionInfo;
@ -26,7 +27,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
@ -47,12 +47,6 @@ import java.util.stream.Collectors;
@Service
public class SysUserServiceImpl implements ISysUserService {
private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);
@Value("${system.supports.phoneLogin}")
private boolean supportsPhoneLogin;
@Value("${system.supports.emailLogin}")
private boolean supportsEmailLogin;
@Autowired
private SysUserMapper userMapper;
@ -146,16 +140,29 @@ public class SysUserServiceImpl implements ISysUserService {
*/
@Override
public SysUser selectUserByUserName(String userName) {
String loginType = "0";
if (supportsEmailLogin && supportsPhoneLogin) {
loginType = "3";
} else if (supportsEmailLogin) {
loginType = "2";
} else if (supportsPhoneLogin) {
loginType = "1";
return userMapper.selectUserByUserName(userName);
}
return userMapper.selectUserByUserName(userName, loginType);
/**
* 通过用户名查询用户
*
* @param photoNumber 用户名
* @return 用户对象信息
*/
@Override
public SysUser selectUserByPhotoNumber(String photoNumber) {
return userMapper.selectUserByUserName(photoNumber);
}
/**
* 通过用户名查询用户
*
* @param email 用户名
* @return 用户对象信息
*/
@Override
public SysUser selectUserByEmail(String email) {
return userMapper.selectUserByUserName(email);
}
/**
@ -257,6 +264,11 @@ public class SysUserServiceImpl implements ISysUserService {
return UserConstants.UNIQUE;
}
/**
* @return
*/
/**
* 校验用户是否允许操作
*
@ -511,16 +523,8 @@ public class SysUserServiceImpl implements ISysUserService {
StringBuilder failureMsg = new StringBuilder();
for (SysUser user : userList) {
try {
String loginType = "0";
if (supportsEmailLogin && supportsPhoneLogin) {
loginType = "3";
} else if (supportsEmailLogin) {
loginType = "2";
} else if (supportsPhoneLogin) {
loginType = "1";
}
// 验证是否存在这个用户
SysUser u = userMapper.selectUserByUserName(user.getUserName(), loginType);
SysUser u = userMapper.selectUserByUserName(user.getUserName());
if (StringUtils.isNull(u)) {
BeanValidators.validateWithException(validator, user);
deptService.checkDeptDataScope(user.getDeptId());

View File

@ -158,20 +158,16 @@
<select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult">
<include refid="selectUserVo"/>
where u.del_flag = '0'AND (u.user_name = #{userName}
<if test="loginType != null and loginType == '1'.toString()">
OR u.phonenumber = #{userName}
</if>
<if test="loginType != null and loginType == '2'.toString()">
OR u.email = #{userName}
</if>
<if test="loginType != null and loginType == '3'.toString()">
OR u.phonenumber = #{userName}
OR u.email = #{userName}
</if>
)
where u.del_flag = '0'AND u.user_name = #{userName}
</select>
<select id="selectUserByPhoneNumber" resultType="com.bonus.system.api.domain.SysUser">
<include refid="selectUserVo"/>
where u.del_flag = '0'AND u.phonenumber = #{phoneNumber}
</select>
<select id="selectUserByEmail" resultType="com.bonus.system.api.domain.SysUser">
<include refid="selectUserVo"/>
where u.del_flag = '0'AND u.email = #{email}
</select>
<select id="selectUserById" parameterType="Long" resultMap="SysUserResult">
<include refid="selectUserVo"/>
where u.user_id = #{userId}
@ -269,6 +265,8 @@
</select>
<insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
insert into sys_user(
<if test="userId != null and userId != 0">user_id,</if>
@ -364,4 +362,5 @@
</foreach>
</delete>
</mapper>

View File

@ -210,6 +210,12 @@
<version>${bonus.version}</version>
</dependency>
<dependency>
<groupId>com.bonus</groupId>
<artifactId>bonus-common-config</artifactId>
<version>${bonus.version}</version>
</dependency>
<!-- 缓存服务 -->
<dependency>
<groupId>com.bonus</groupId>
@ -234,6 +240,7 @@
<module>bonus-modules</module>
<module>bonus-api</module>
<module>bonus-common</module>
<module>bonus-common/bonus-common-config</module>
</modules>
<packaging>pom</packaging>