用户登录问题修改
This commit is contained in:
parent
5c340f728c
commit
e0b41291b3
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.bonus.auth.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author bonus
|
||||||
|
*/
|
||||||
|
|
||||||
|
public enum VerificationCodeType {
|
||||||
|
/**
|
||||||
|
* 登录
|
||||||
|
*/
|
||||||
|
LOGIN,
|
||||||
|
/**
|
||||||
|
* 注册
|
||||||
|
*/
|
||||||
|
REGISTER;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static VerificationCodeType fromString(String key) {
|
||||||
|
if (key == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自定义转换逻辑,允许大小写不敏感的匹配
|
||||||
|
for (VerificationCodeType type : VerificationCodeType.values()) {
|
||||||
|
if (type.name().equalsIgnoreCase(key)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// throw new ServiceException("不支持的登录方式");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.bonus.auth.controller;
|
package com.bonus.auth.controller;
|
||||||
|
|
||||||
import com.bonus.auth.config.LoginType;
|
|
||||||
import com.bonus.auth.factory.LoginStrategyFactory;
|
import com.bonus.auth.factory.LoginStrategyFactory;
|
||||||
import com.bonus.auth.form.LoginBody;
|
import com.bonus.auth.form.LoginBody;
|
||||||
import com.bonus.auth.form.RegisterBody;
|
import com.bonus.auth.form.RegisterBody;
|
||||||
|
|
@ -61,7 +60,7 @@ public class TokenController {
|
||||||
|
|
||||||
@PostMapping("isAdmin")
|
@PostMapping("isAdmin")
|
||||||
public R<?> isAdmin(@RequestBody LoginBody form) {
|
public R<?> isAdmin(@RequestBody LoginBody form) {
|
||||||
if (!isAdmin){
|
if (!isAdmin) {
|
||||||
return R.ok(false);
|
return R.ok(false);
|
||||||
}
|
}
|
||||||
passwordValidatorService.validateLoginParameters(form.getUsername(), form.getPassword());
|
passwordValidatorService.validateLoginParameters(form.getUsername(), form.getPassword());
|
||||||
|
|
@ -78,7 +77,7 @@ public class TokenController {
|
||||||
passwordService.validate(user, form.getPassword(), System.currentTimeMillis());
|
passwordService.validate(user, form.getPassword(), System.currentTimeMillis());
|
||||||
// 处理IP校验
|
// 处理IP校验
|
||||||
passwordValidatorService.handleIpValidation(form.getUsername(), user);
|
passwordValidatorService.handleIpValidation(form.getUsername(), user);
|
||||||
if (userResult == null || userResult.getData() == null || R.FAIL == userResult.getCode()) {
|
if (userResult.getData() == null || R.FAIL == userResult.getCode()) {
|
||||||
return R.fail("登录用户不存在");
|
return R.fail("登录用户不存在");
|
||||||
}
|
}
|
||||||
Set<String> roles = userResult.getData().getRoles();
|
Set<String> roles = userResult.getData().getRoles();
|
||||||
|
|
@ -97,19 +96,13 @@ public class TokenController {
|
||||||
|
|
||||||
@PostMapping("login")
|
@PostMapping("login")
|
||||||
public R<?> login(@RequestBody LoginBody form) {
|
public R<?> login(@RequestBody LoginBody form) {
|
||||||
|
|
||||||
// 获取相应的登录策略
|
// 获取相应的登录策略
|
||||||
LoginStrategy strategy = loginStrategyFactory.getStrategy(form.getLoginType());
|
LoginStrategy strategy = loginStrategyFactory.getStrategy(form.getLoginType());
|
||||||
if (strategy == null) {
|
if (strategy == null) {
|
||||||
return R.fail("不支持的登录方式");
|
return R.fail("不支持的登录方式");
|
||||||
}
|
}
|
||||||
LoginUser login = strategy.login(form.getUsername(), form.getPassword());
|
LoginUser login = strategy.login(form.getUsername(), form.getPassword());
|
||||||
if (login.getRoles().contains("admin") && form.getLoginType().equals(LoginType.USERNAME_PASSWORD) && isAdmin) {
|
|
||||||
passwordValidatorService.checkPhoneCaptcha(form.getVerificationCode(), login.getSysUser().getPhonenumber());
|
|
||||||
return R.ok(tokenService.createToken(login));
|
return R.ok(tokenService.createToken(login));
|
||||||
} else {
|
|
||||||
return R.ok(tokenService.createToken(login));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,7 +114,7 @@ public class TokenController {
|
||||||
*/
|
*/
|
||||||
@PostMapping("getPhoneCode")
|
@PostMapping("getPhoneCode")
|
||||||
public R<?> getPhoneCode(@RequestBody LoginBody form) {
|
public R<?> getPhoneCode(@RequestBody LoginBody form) {
|
||||||
return sysLoginService.getPhoneCode(form.getMobile(), form.getMobileCodeType());
|
return sysLoginService.getPhoneCode(form.getUsername(), form.getVerificationCodeType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.bonus.auth.factory;
|
||||||
|
|
||||||
|
import com.bonus.auth.config.VerificationCodeType;
|
||||||
|
import com.bonus.auth.service.LoginVerificationCodeSender;
|
||||||
|
import com.bonus.auth.service.RegisterVerificationCodeSender;
|
||||||
|
import com.bonus.auth.service.VerificationCodeStrategy;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author bonus
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class VerificationCodeStrategyFactory {
|
||||||
|
private final Map<VerificationCodeType, VerificationCodeStrategy> strategyMap;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public VerificationCodeStrategyFactory(List<VerificationCodeStrategy> strategies) {
|
||||||
|
strategyMap = new HashMap<>();
|
||||||
|
// 通过类型查找对应的策略
|
||||||
|
strategies.forEach(strategy -> {
|
||||||
|
if (strategy instanceof LoginVerificationCodeSender) {
|
||||||
|
strategyMap.put(VerificationCodeType.LOGIN, strategy);
|
||||||
|
} else if (strategy instanceof RegisterVerificationCodeSender) {
|
||||||
|
strategyMap.put(VerificationCodeType.REGISTER, strategy);
|
||||||
|
}
|
||||||
|
// 继续添加其他策略
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public VerificationCodeStrategy getStrategy(VerificationCodeType verificationCodeType) {
|
||||||
|
return strategyMap.get(verificationCodeType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.bonus.auth.form;
|
package com.bonus.auth.form;
|
||||||
|
|
||||||
import com.bonus.auth.config.LoginType;
|
import com.bonus.auth.config.LoginType;
|
||||||
|
import com.bonus.auth.config.VerificationCodeType;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -33,6 +34,8 @@ public class LoginBody {
|
||||||
|
|
||||||
private LoginType loginType;
|
private LoginType loginType;
|
||||||
|
|
||||||
|
private VerificationCodeType verificationCodeType;
|
||||||
|
|
||||||
private String mobileCodeType;
|
private String mobileCodeType;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
package com.bonus.auth.service;
|
|
||||||
|
|
||||||
import com.bonus.common.core.constant.CacheConstants;
|
|
||||||
import com.bonus.common.core.constant.Constants;
|
|
||||||
import com.bonus.common.core.domain.R;
|
|
||||||
import com.bonus.common.core.utils.VerificationCodeUtils;
|
|
||||||
import com.bonus.common.redis.service.RedisService;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.mail.SimpleMailMessage;
|
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class EmailService {
|
|
||||||
@Autowired
|
|
||||||
private RedisService redisService;
|
|
||||||
@Autowired
|
|
||||||
private JavaMailSender mailSender; // 自动注入JavaMailSender,用于发送邮件
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送简单邮件
|
|
||||||
*
|
|
||||||
* @param to 接收者邮箱地址
|
|
||||||
*/
|
|
||||||
public R<Object> sendSimpleEmail(String to) {
|
|
||||||
// 创建一个简单邮件消息对象
|
|
||||||
String code = VerificationCodeUtils.generateVerificationCode(VerificationCodeUtils.CodeType.NUMERIC);
|
|
||||||
String str = "您的验证码为" + code + ",尊敬的客户,以上验证码3分钟有效,微服务平台提醒您:转发可能导致账号被盗,请勿将验证码泄露于他人";
|
|
||||||
SimpleMailMessage message = new SimpleMailMessage();
|
|
||||||
// 发件人邮箱地址
|
|
||||||
message.setFrom("2642480752@qq.com");
|
|
||||||
// 收件人邮箱地址
|
|
||||||
message.setTo(to);
|
|
||||||
// 邮件主题
|
|
||||||
message.setSubject("【博诺思】");
|
|
||||||
// 邮件内容
|
|
||||||
message.setText(str);
|
|
||||||
// 发送邮件
|
|
||||||
mailSender.send(message);
|
|
||||||
String verifyKey = CacheConstants.CAPTCHA_PHONE_CODE_KEY + to;
|
|
||||||
redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
|
|
||||||
return R.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
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.common.security.service.EmailService;
|
||||||
|
import com.bonus.common.security.service.SmsService;
|
||||||
|
import com.bonus.system.api.RemoteUserService;
|
||||||
|
import com.bonus.system.api.model.LoginUser;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码发送服务
|
||||||
|
* 可发送到邮箱或手机
|
||||||
|
*
|
||||||
|
* @author bonus
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class LoginVerificationCodeSender implements VerificationCodeStrategy {
|
||||||
|
|
||||||
|
private static final String EMAIL_REGEX = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
|
||||||
|
private static final String PHONE_REGEX = "^1[3-9]\\d{9}$";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private EmailService emailService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SmsService smsService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RemoteUserService remoteUserService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送验证码到邮箱或手机
|
||||||
|
*
|
||||||
|
* @param contactInfo 可以是邮箱地址或手机号码
|
||||||
|
* @return 验证码发送的结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String sendVerificationCode(String contactInfo) {
|
||||||
|
if (isEmail(contactInfo)) {
|
||||||
|
return emailService.sendSimpleEmail(contactInfo);
|
||||||
|
} else if (isPhone(contactInfo)) {
|
||||||
|
return smsService.sendSimplePhone(contactInfo);
|
||||||
|
} else {
|
||||||
|
return handleUsernameLogin(contactInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否是邮箱
|
||||||
|
*
|
||||||
|
* @param contactInfo 输入信息
|
||||||
|
* @return 是否为邮箱
|
||||||
|
*/
|
||||||
|
private boolean isEmail(String contactInfo) {
|
||||||
|
return contactInfo.matches(EMAIL_REGEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否是手机号
|
||||||
|
*
|
||||||
|
* @param contactInfo 输入信息
|
||||||
|
* @return 是否为手机号
|
||||||
|
*/
|
||||||
|
private boolean isPhone(String contactInfo) {
|
||||||
|
return contactInfo.matches(PHONE_REGEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理用户名登录逻辑
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @return 验证码发送的结果
|
||||||
|
*/
|
||||||
|
private String handleUsernameLogin(String username) {
|
||||||
|
R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
|
||||||
|
if (userResult == null || userResult.getData() == null || R.FAIL == userResult.getCode()) {
|
||||||
|
throw new ServiceException("用户名/密码错误");
|
||||||
|
}
|
||||||
|
LoginUser user = userResult.getData();
|
||||||
|
// 如果用户是管理员,则发送手机验证码
|
||||||
|
if (user.getRoles().contains("admin")) {
|
||||||
|
if (StringUtils.isEmpty(user.getSysUser().getPhonenumber())) {
|
||||||
|
throw new ServiceException("此账号未绑定手机号,请先绑定手机号");
|
||||||
|
}
|
||||||
|
return smsService.sendSimplePhone(user.getSysUser().getPhonenumber());
|
||||||
|
} else {
|
||||||
|
throw new ServiceException("不支持的登录方式");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -236,7 +236,7 @@ public class PasswordValidatorService {
|
||||||
if (StringUtils.isEmpty(phone)) {
|
if (StringUtils.isEmpty(phone)) {
|
||||||
throw new CaptchaException("手机号不能为空");
|
throw new CaptchaException("手机号不能为空");
|
||||||
}
|
}
|
||||||
String verifyKey = CacheConstants.CAPTCHA_PHONE_CODE_KEY + StringUtils.nvl(phone, "");
|
String verifyKey = CacheConstants.VERIFICATION_CODE + StringUtils.nvl(phone, "");
|
||||||
String captcha = redisService.getCacheObject(verifyKey);
|
String captcha = redisService.getCacheObject(verifyKey);
|
||||||
if (captcha == null) {
|
if (captcha == null) {
|
||||||
throw new CaptchaException("手机验证码已失效");
|
throw new CaptchaException("手机验证码已失效");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
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.common.security.service.EmailService;
|
||||||
|
import com.bonus.common.security.service.SmsService;
|
||||||
|
import com.bonus.system.api.RemoteUserService;
|
||||||
|
import com.bonus.system.api.model.LoginUser;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author bonus
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class RegisterVerificationCodeSender implements VerificationCodeStrategy {
|
||||||
|
|
||||||
|
private static final String EMAIL_REGEX = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
|
||||||
|
private static final String PHONE_REGEX = "^1[3-9]\\d{9}$";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private EmailService emailService;
|
||||||
|
@Resource
|
||||||
|
private SmsService smsService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RemoteUserService remoteUserService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送验证码到邮箱或手机
|
||||||
|
*
|
||||||
|
* @param contactInfo 可以是邮箱地址或手机号码
|
||||||
|
* @return 验证码发送的结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String sendVerificationCode(String contactInfo) {
|
||||||
|
R<LoginUser> userResult = remoteUserService.getUserInfo(contactInfo, SecurityConstants.INNER);
|
||||||
|
if (userResult.getData() != null) {
|
||||||
|
throw new ServiceException("联系方式已经注册账号");
|
||||||
|
}
|
||||||
|
if (isEmail(contactInfo)) {
|
||||||
|
return emailService.sendSimpleEmail(contactInfo);
|
||||||
|
} else if (isPhone(contactInfo)) {
|
||||||
|
return smsService.sendSimplePhone(contactInfo);
|
||||||
|
} else {
|
||||||
|
throw new ServiceException("请输入正确的联系方式");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否是邮箱
|
||||||
|
*
|
||||||
|
* @param contactInfo 输入信息
|
||||||
|
* @return 是否为邮箱
|
||||||
|
*/
|
||||||
|
private boolean isEmail(String contactInfo) {
|
||||||
|
return contactInfo.matches(EMAIL_REGEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否是手机号
|
||||||
|
*
|
||||||
|
* @param contactInfo 输入信息
|
||||||
|
* @return 是否为手机号
|
||||||
|
*/
|
||||||
|
private boolean isPhone(String contactInfo) {
|
||||||
|
return contactInfo.matches(PHONE_REGEX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package com.bonus.auth.service;
|
package com.bonus.auth.service;
|
||||||
|
|
||||||
|
import com.bonus.auth.config.VerificationCodeType;
|
||||||
|
import com.bonus.auth.factory.VerificationCodeStrategyFactory;
|
||||||
import com.bonus.auth.form.RegisterBody;
|
import com.bonus.auth.form.RegisterBody;
|
||||||
import com.bonus.common.core.constant.Constants;
|
import com.bonus.common.core.constant.Constants;
|
||||||
import com.bonus.common.core.constant.SecurityConstants;
|
import com.bonus.common.core.constant.SecurityConstants;
|
||||||
|
|
@ -8,15 +10,11 @@ import com.bonus.common.core.domain.R;
|
||||||
import com.bonus.common.core.exception.ServiceException;
|
import com.bonus.common.core.exception.ServiceException;
|
||||||
import com.bonus.common.core.utils.StringUtils;
|
import com.bonus.common.core.utils.StringUtils;
|
||||||
import com.bonus.common.core.web.domain.AjaxResult;
|
import com.bonus.common.core.web.domain.AjaxResult;
|
||||||
import com.bonus.common.redis.service.RedisService;
|
|
||||||
import com.bonus.common.security.utils.SecurityUtils;
|
import com.bonus.common.security.utils.SecurityUtils;
|
||||||
import com.bonus.system.api.RemoteUserService;
|
import com.bonus.system.api.RemoteUserService;
|
||||||
import com.bonus.system.api.domain.SysUser;
|
import com.bonus.system.api.domain.SysUser;
|
||||||
import com.bonus.system.api.model.LoginUser;
|
|
||||||
import com.hankcs.hanlp.HanLP;
|
import com.hankcs.hanlp.HanLP;
|
||||||
import org.apache.poi.ss.formula.functions.T;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
@ -30,115 +28,31 @@ public class SysLoginService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private RemoteUserService remoteUserService;
|
private RemoteUserService remoteUserService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SysPasswordService passwordService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SysRecordLogService recordLogService;
|
private SysRecordLogService recordLogService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RedisService redisService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private EmailService emailService;
|
|
||||||
|
|
||||||
@Value("${system.supports.phoneLogin}")
|
|
||||||
private boolean supportsPhoneLogin;
|
|
||||||
|
|
||||||
@Value("${system.supports.emailLogin}")
|
|
||||||
private boolean supportsEmailLogin;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private PasswordValidatorService passwordValidatorService;
|
private PasswordValidatorService passwordValidatorService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private VerificationCodeStrategyFactory verificationCodeStrategyFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取验证码
|
* 获取验证码
|
||||||
*
|
*
|
||||||
* @param username 用户名或手机号
|
* @param username 用户名或手机号
|
||||||
* @param getMobileCodeType 获取验证码类型(register:注册,其他:登录)
|
* @param verificationCodeType 获取验证码类型(register:注册,其他:登录)
|
||||||
* @return 响应结果
|
* @return 响应结果
|
||||||
*/
|
*/
|
||||||
public R<T> getPhoneCode(String username, String getMobileCodeType) {
|
public R<?> getPhoneCode(String username, VerificationCodeType verificationCodeType) {
|
||||||
// 记录开始时间
|
// 获取相应的登录策略
|
||||||
long startTime = System.currentTimeMillis();
|
VerificationCodeStrategy strategyFactory = verificationCodeStrategyFactory.getStrategy(verificationCodeType);
|
||||||
int contactType = getContactType(username);
|
if (strategyFactory == null) {
|
||||||
R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
|
return R.fail("不支持的方式");
|
||||||
boolean userExists = userResult != null && userResult.getData() != null;
|
|
||||||
if (userResult.getData().getRoles().contains("admin")) {
|
|
||||||
passwordService.createPhoneCaptcha(userResult.getData().getSysUser().getPhonenumber());
|
|
||||||
return R.ok();
|
|
||||||
}
|
}
|
||||||
if (contactType == 2) {
|
return R.ok(strategyFactory.sendVerificationCode(username));
|
||||||
recordLogService.saveLogs(username, startTime, "获取验证码失败", "联系方式无效", null, "失败");
|
|
||||||
throw new ServiceException("请输入正确的联系方式");
|
|
||||||
}
|
|
||||||
if ("register".equals(getMobileCodeType)) {
|
|
||||||
handleRegister(username, startTime, contactType, userExists);
|
|
||||||
} else {
|
|
||||||
handleLogin(username, startTime, contactType, userExists);
|
|
||||||
}
|
|
||||||
return R.ok();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理注册操作
|
|
||||||
*
|
|
||||||
* @param username 用户名或手机号
|
|
||||||
* @param startTime 操作开始时间
|
|
||||||
* @param contactType 联系方式类型(0:邮箱,1:手机号,2:无效)
|
|
||||||
* @param userExists 用户是否存在
|
|
||||||
*/
|
|
||||||
private void handleRegister(String username, long startTime, int contactType, boolean userExists) {
|
|
||||||
if (userExists) {
|
|
||||||
recordLogService.saveLogs(username, startTime, contactType == 0 ? "获取邮箱验证码" : "获取手机验证码",
|
|
||||||
contactType == 0 ? "此邮箱已注册" : "此手机号已注册", null, "失败");
|
|
||||||
throw new ServiceException(contactType == 0 ? "此邮箱已注册" : "此手机号已注册");
|
|
||||||
}
|
|
||||||
if (contactType == 0) {
|
|
||||||
if (!supportsEmailLogin) {
|
|
||||||
recordLogService.saveLogs(username, startTime, "邮箱登录不支持", "邮箱登录未开启", null, "失败");
|
|
||||||
throw new ServiceException("邮箱登录未开启");
|
|
||||||
}
|
|
||||||
emailService.sendSimpleEmail(username);
|
|
||||||
} else {
|
|
||||||
if (!supportsPhoneLogin) {
|
|
||||||
recordLogService.saveLogs(username, startTime, "手机登录不支持", "手机登录未开启", null, "失败");
|
|
||||||
throw new ServiceException("手机登录未开启");
|
|
||||||
}
|
|
||||||
passwordService.createPhoneCaptcha(username);
|
|
||||||
}
|
|
||||||
recordLogService.saveLogs(username, startTime, contactType == 0 ? "获取邮箱验证码" : "获取手机验证码",
|
|
||||||
contactType == 0 ? "邮箱注册" : "手机号注册", null, "成功");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理登录操作
|
|
||||||
*
|
|
||||||
* @param username 用户名或手机号
|
|
||||||
* @param startTime 操作开始时间
|
|
||||||
* @param contactType 联系方式类型(0:邮箱,1:手机号,2:无效)
|
|
||||||
* @param userExists 用户是否存在
|
|
||||||
*/
|
|
||||||
private void handleLogin(String username, long startTime, int contactType, boolean userExists) {
|
|
||||||
if (!userExists) {
|
|
||||||
recordLogService.saveLogs(username, startTime, "登录用户不存在", "手机号未注册", null, "失败");
|
|
||||||
throw new ServiceException("登录用户不存在");
|
|
||||||
}
|
|
||||||
if (contactType == 0) {
|
|
||||||
if (!supportsEmailLogin) {
|
|
||||||
recordLogService.saveLogs(username, startTime, "邮箱登录不支持", "邮箱登录未开启", null, "失败");
|
|
||||||
throw new ServiceException("邮箱登录未开启");
|
|
||||||
}
|
|
||||||
emailService.sendSimpleEmail(username);
|
|
||||||
} else {
|
|
||||||
if (!supportsPhoneLogin) {
|
|
||||||
recordLogService.saveLogs(username, startTime, "手机登录不支持", "手机登录未开启", null, "失败");
|
|
||||||
throw new ServiceException("手机登录未开启");
|
|
||||||
}
|
|
||||||
passwordService.createPhoneCaptcha(username);
|
|
||||||
}
|
|
||||||
recordLogService.saveLogs(username, startTime, "获取验证码", "用户存在", null, "成功");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -182,9 +96,7 @@ public class SysLoginService {
|
||||||
sysUser.setStatus("1");
|
sysUser.setStatus("1");
|
||||||
sysUser.setApprovalStatus("0");
|
sysUser.setApprovalStatus("0");
|
||||||
//有要求另加
|
//有要求另加
|
||||||
|
|
||||||
sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword()));
|
sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword()));
|
||||||
|
|
||||||
if (getContactType(registerBody.getMobile()) == 1) {
|
if (getContactType(registerBody.getMobile()) == 1) {
|
||||||
sysUser.setPhonenumber(registerBody.getMobile());
|
sysUser.setPhonenumber(registerBody.getMobile());
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -214,7 +126,6 @@ public class SysLoginService {
|
||||||
public static int getContactType(String contactInfo) {
|
public static int getContactType(String contactInfo) {
|
||||||
String emailRegex = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
|
String emailRegex = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
|
||||||
String phoneRegex = "^1[3-9]\\d{9}$";
|
String phoneRegex = "^1[3-9]\\d{9}$";
|
||||||
|
|
||||||
if (contactInfo.matches(emailRegex)) {
|
if (contactInfo.matches(emailRegex)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (contactInfo.matches(phoneRegex)) {
|
} else if (contactInfo.matches(phoneRegex)) {
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ public class SysPasswordService {
|
||||||
}
|
}
|
||||||
String code = VerificationCodeUtils.generateVerificationCode(VerificationCodeUtils.CodeType.NUMERIC);
|
String code = VerificationCodeUtils.generateVerificationCode(VerificationCodeUtils.CodeType.NUMERIC);
|
||||||
String str = "您的验证码为" + code + ",尊敬的客户,以上验证码3分钟有效,微服务平台提醒您:转发可能导致账号被盗,请勿将验证码泄露于他人";
|
String str = "您的验证码为" + code + ",尊敬的客户,以上验证码3分钟有效,微服务平台提醒您:转发可能导致账号被盗,请勿将验证码泄露于他人";
|
||||||
String verifyKey = CacheConstants.CAPTCHA_PHONE_CODE_KEY + phone;
|
String verifyKey = CacheConstants.VERIFICATION_CODE + phone;
|
||||||
String s = SmsUtils.smsToken(phone, str, "");
|
String s = SmsUtils.smsToken(phone, str, "");
|
||||||
if (StringUtils.isNotEmpty(s)) {
|
if (StringUtils.isNotEmpty(s)) {
|
||||||
if (s.contains("ok")) {
|
if (s.contains("ok")) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.bonus.auth.service;
|
||||||
|
|
||||||
|
public interface VerificationCodeStrategy {
|
||||||
|
/**
|
||||||
|
* @param contactInfo 可以是邮箱地址或手机号码
|
||||||
|
*/
|
||||||
|
String sendVerificationCode(String contactInfo);
|
||||||
|
}
|
||||||
|
|
@ -33,6 +33,10 @@
|
||||||
<groupId>com.bonus</groupId>
|
<groupId>com.bonus</groupId>
|
||||||
<artifactId>bonus-common-redis</artifactId>
|
<artifactId>bonus-common-redis</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-mail</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.bonus.common.security.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author bonus
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "verification-code")
|
||||||
|
@Data
|
||||||
|
public class VerificationCodeConfig {
|
||||||
|
/**
|
||||||
|
* 主题
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
/**
|
||||||
|
* 过期时长
|
||||||
|
*/
|
||||||
|
private Long time;
|
||||||
|
/**
|
||||||
|
* 内容
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.bonus.common.security.service;
|
||||||
|
|
||||||
|
import com.bonus.common.core.constant.CacheConstants;
|
||||||
|
import com.bonus.common.core.utils.StringUtils;
|
||||||
|
import com.bonus.common.core.utils.VerificationCodeUtils;
|
||||||
|
import com.bonus.common.redis.service.RedisService;
|
||||||
|
import com.bonus.common.security.config.VerificationCodeConfig;
|
||||||
|
import org.springframework.mail.SimpleMailMessage;
|
||||||
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static com.bonus.common.core.utils.VerificationCodeUtils.CodeType.NUMERIC;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author bonus
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class EmailService {
|
||||||
|
@Resource
|
||||||
|
private VerificationCodeConfig verificationCodeConfig;
|
||||||
|
@Resource
|
||||||
|
private RedisService redisService;
|
||||||
|
@Resource
|
||||||
|
private JavaMailSender mailSender;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送简单邮件
|
||||||
|
*
|
||||||
|
* @param to 接收者邮箱地址
|
||||||
|
*/
|
||||||
|
public String sendSimpleEmail(String to) {
|
||||||
|
String code = VerificationCodeUtils.generateVerificationCode(NUMERIC);
|
||||||
|
String str = verificationCodeConfig.getContent().replace("<code>", code);
|
||||||
|
str = str.replace("<time>", verificationCodeConfig.getTime().toString());
|
||||||
|
SimpleMailMessage message = new SimpleMailMessage();
|
||||||
|
// 发件人邮箱地址
|
||||||
|
message.setFrom("2642480752@qq.com");
|
||||||
|
// 收件人邮箱地址
|
||||||
|
message.setTo(to);
|
||||||
|
// 邮件主题
|
||||||
|
message.setSubject(verificationCodeConfig.getTitle());
|
||||||
|
// 邮件内容
|
||||||
|
message.setText(str);
|
||||||
|
// 发送邮件
|
||||||
|
mailSender.send(message);
|
||||||
|
String uuid = StringUtils.randomUUID();
|
||||||
|
String verifyKey = CacheConstants.VERIFICATION_CODE + uuid;
|
||||||
|
redisService.setCacheObject(verifyKey, code, verificationCodeConfig.getTime(), TimeUnit.MINUTES);
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.bonus.common.security.service;
|
||||||
|
|
||||||
|
import com.bonus.common.core.constant.CacheConstants;
|
||||||
|
import com.bonus.common.core.exception.CaptchaException;
|
||||||
|
import com.bonus.common.core.utils.StringUtils;
|
||||||
|
import com.bonus.common.core.utils.VerificationCodeUtils;
|
||||||
|
import com.bonus.common.core.utils.sms.SmsUtils;
|
||||||
|
import com.bonus.common.redis.service.RedisService;
|
||||||
|
import com.bonus.common.security.config.VerificationCodeConfig;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static com.bonus.common.core.utils.VerificationCodeUtils.CodeType.NUMERIC;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author bonus
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SmsService {
|
||||||
|
@Resource
|
||||||
|
private VerificationCodeConfig verificationCodeConfig;
|
||||||
|
@Resource
|
||||||
|
private RedisService redisService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成手机验证码
|
||||||
|
*
|
||||||
|
* @return AjaxResult
|
||||||
|
* @throws CaptchaException 自定义captcha 异常
|
||||||
|
*/
|
||||||
|
public String sendSimplePhone(String to) {
|
||||||
|
if (StringUtils.isEmpty(to)) {
|
||||||
|
throw new CaptchaException("手机号不能为空");
|
||||||
|
}
|
||||||
|
String code = VerificationCodeUtils.generateVerificationCode(NUMERIC);
|
||||||
|
String str = verificationCodeConfig.getContent().replace("<code>", code);
|
||||||
|
str = str.replace("<time>", verificationCodeConfig.getTime().toString());
|
||||||
|
String s = SmsUtils.smsToken(to, str, "");
|
||||||
|
if (StringUtils.isNotEmpty(s)) {
|
||||||
|
if (s.contains("ok")) {
|
||||||
|
String uuid = StringUtils.randomUUID();
|
||||||
|
String verifyKey = CacheConstants.VERIFICATION_CODE + uuid;
|
||||||
|
redisService.setCacheObject(verifyKey, code, verificationCodeConfig.getTime(), TimeUnit.MINUTES);
|
||||||
|
return uuid;
|
||||||
|
} else {
|
||||||
|
throw new CaptchaException("获取短信失败");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new CaptchaException("获取短信失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,21 +1,5 @@
|
||||||
package com.bonus.common.security.service;
|
package com.bonus.common.security.service;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import com.bonus.common.core.constant.Constants;
|
|
||||||
import com.bonus.common.core.domain.R;
|
|
||||||
import com.bonus.common.core.exception.CaptchaException;
|
|
||||||
import com.bonus.common.core.utils.VerificationCodeUtils;
|
|
||||||
import com.bonus.common.core.utils.sms.SmsUtils;
|
|
||||||
import com.bonus.common.core.web.domain.AjaxResult;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import com.bonus.common.core.constant.CacheConstants;
|
import com.bonus.common.core.constant.CacheConstants;
|
||||||
import com.bonus.common.core.constant.SecurityConstants;
|
import com.bonus.common.core.constant.SecurityConstants;
|
||||||
import com.bonus.common.core.utils.JwtUtils;
|
import com.bonus.common.core.utils.JwtUtils;
|
||||||
|
|
@ -26,6 +10,16 @@ import com.bonus.common.core.utils.uuid.IdUtils;
|
||||||
import com.bonus.common.redis.service.RedisService;
|
import com.bonus.common.redis.service.RedisService;
|
||||||
import com.bonus.common.security.utils.SecurityUtils;
|
import com.bonus.common.security.utils.SecurityUtils;
|
||||||
import com.bonus.system.api.model.LoginUser;
|
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.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* token验证处理
|
* token验证处理
|
||||||
|
|
@ -34,6 +28,9 @@ import com.bonus.system.api.model.LoginUser;
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class TokenService {
|
public class TokenService {
|
||||||
|
@Value("${tokenTime}")
|
||||||
|
private Long tokenTime;
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(TokenService.class);
|
private static final Logger log = LoggerFactory.getLogger(TokenService.class);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
@ -48,6 +45,7 @@ public class TokenService {
|
||||||
private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY;
|
private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY;
|
||||||
|
|
||||||
private final static String LOGIN_USER_KEY = CacheConstants.LOGIN_USER_KEY;
|
private final static String LOGIN_USER_KEY = CacheConstants.LOGIN_USER_KEY;
|
||||||
|
|
||||||
private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE;
|
private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -74,7 +72,7 @@ public class TokenService {
|
||||||
rspMap.put("access_token", accessToken);
|
rspMap.put("access_token", accessToken);
|
||||||
rspMap.put("expires_in", EXPIRETIME);
|
rspMap.put("expires_in", EXPIRETIME);
|
||||||
//对token进行存储
|
//对token进行存储
|
||||||
redisService.setCacheObject(LOGIN_USER_KEY + userId, token, 120L, TimeUnit.MINUTES);
|
redisService.setCacheObject(LOGIN_USER_KEY + userId, token, tokenTime, TimeUnit.MINUTES);
|
||||||
return rspMap;
|
return rspMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,10 +174,10 @@ public class TokenService {
|
||||||
*/
|
*/
|
||||||
public void refreshToken(LoginUser loginUser) {
|
public void refreshToken(LoginUser loginUser) {
|
||||||
loginUser.setLoginTime(System.currentTimeMillis());
|
loginUser.setLoginTime(System.currentTimeMillis());
|
||||||
loginUser.setExpireTime(loginUser.getLoginTime() + EXPIRETIME * MILLIS_MINUTE);
|
loginUser.setExpireTime(loginUser.getLoginTime() + tokenTime * MILLIS_MINUTE);
|
||||||
// 根据uuid将loginUser缓存
|
// 根据uuid将loginUser缓存
|
||||||
String userKey = getTokenKey(loginUser.getToken());
|
String userKey = getTokenKey(loginUser.getToken());
|
||||||
redisService.setCacheObject(userKey, loginUser, EXPIRETIME, TimeUnit.MINUTES);
|
redisService.setCacheObject(userKey, loginUser, tokenTime, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTokenKey(String token) {
|
private String getTokenKey(String token) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
com.bonus.common.security.config.WebMvcConfig
|
com.bonus.common.security.config.WebMvcConfig
|
||||||
|
com.bonus.common.security.config.VerificationCodeConfig
|
||||||
com.bonus.common.security.service.TokenService
|
com.bonus.common.security.service.TokenService
|
||||||
|
com.bonus.common.security.service.SmsService
|
||||||
|
com.bonus.common.security.service.EmailService
|
||||||
com.bonus.common.security.aspect.PreAuthorizeAspect
|
com.bonus.common.security.aspect.PreAuthorizeAspect
|
||||||
com.bonus.common.security.aspect.InnerAuthAspect
|
com.bonus.common.security.aspect.InnerAuthAspect
|
||||||
com.bonus.common.security.handler.GlobalExceptionHandler
|
com.bonus.common.security.handler.GlobalExceptionHandler
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue