oauth2-重构梳理AccountController

This commit is contained in:
khalil
2023-11-10 12:17:22 +08:00
parent fddbd82877
commit 7449520db2
161 changed files with 296 additions and 1161 deletions

View File

@@ -1,11 +1,12 @@
package com.accompany.oauth2.constant;
import com.accompany.common.status.BusiStatus;
import com.accompany.common.status.BusiStatusInterface;
/**
* @author liuguofu
*/
public enum OAuthStatus {
public enum OAuthStatus implements BusiStatusInterface {
ACCESS_DENIED(100,"access denied"), //拒絕訪問
@@ -178,4 +179,14 @@ public enum OAuthStatus {
public String toString() {
return Integer.toString(value);
}
@Override
public int getCode() {
return value();
}
@Override
public String getMessage() {
return getReasonPhrase();
}
}

View File

@@ -0,0 +1,31 @@
package com.accompany.oauth2.result;
import com.accompany.oauth2.constant.OAuthStatus;
public class ServiceRes<T> {
private int code;
private String message;
private T data;
public ServiceRes(OAuthStatus status) {
this(status, null);
}
public ServiceRes(OAuthStatus status, T data) {
this.code = status.value();
this.message = status.getReasonPhrase();
this.data = data;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
public T getData() {
return data;
}
}

View File

@@ -316,53 +316,62 @@ public class AccountManageService {
* @param resetCode
* @return 1:成功 2重置码无效 3用户不存在
*/
public OAuthStatus resetPasswordByResetCode(Long uid, String phone, String password, String resetCode) {
public void resetPasswordByResetCode(Long uid, String phone, String password, String resetCode) {
if (phone.contains("*")) {
Account account = accountService.getById(uid);
if (account == null) {
throw new ServiceException(OAuthStatus.USER_NOT_EXISTED);
}
phone = account.getPhone();
if (!CommonUtil.checkPhoneFormat(account.getPhoneAreaCode(),account.getPhone())) {
throw new ServiceException(OAuthStatus.ACCOUNT_NOT_BIND_PHONE);
}
}
int count = accountService.countByPhone(phone);
if (count > 1) {
throw new ServiceException(OAuthStatus.PHONE_BIND_TOO_MANY_ACCOUNT);
}
Account account = accountService.getAccountByPhone(phone);
if (null == account || (uid != null && !account.getUid().equals(uid)) ) {
return OAuthStatus.PHONE_BIND_ERROR;
throw new ServiceException(OAuthStatus.PHONE_BIND_ERROR);
}
uid = account.getUid();
//检验验证码
if (accountService.verifySmsCodeByCache(phone, resetCode,account.getUid())) {
try {
accountService.resetAccountPwd(account.getUid(), password);
//成功后删除验证码缓存
accountService.delSmsCodeCache(phone,account.getUid());
accountService.delNickPasswordCache(account.getErbanNo());
// 删除用户信息缓存
jedisService.hdel(RedisKey.user.getKey(), account.getUid().toString());
jedisService.hdel(RedisKey.user_summary.getKey(), account.getUid().toString());
accountService.delNickPasswordCache(account.getErbanNo());
return OAuthStatus.SUCCESS;
} catch (Exception e) {
return OAuthStatus.INVALID_SERVICE;
}
} else {
return OAuthStatus.INVALID_IDENTIFYING_CODE;
if (!accountService.verifySmsCodeByCache(phone, resetCode, uid)){
throw new ServiceException(OAuthStatus.INVALID_IDENTIFYING_CODE);
}
accountService.resetAccountPwd(account.getUid(), password);
//成功后删除验证码缓存
accountService.delSmsCodeCache(phone,account.getUid());
//accountService.delNickPasswordCache(account.getErbanNo());
// 删除用户信息缓存
jedisService.hdel(RedisKey.user.getKey(), account.getUid().toString());
jedisService.hdel(RedisKey.user_summary.getKey(), account.getUid().toString());
accountService.delNickPasswordCache(account.getErbanNo());
}
public OAuthStatus resetPasswordByOldPassword(String phone, String password, String newPassword) {
public void resetPasswordByOldPassword(String phone, String password, String newPassword) {
Account account = accountService.getAccountByPhone(phone);
if (null == account) {
return OAuthStatus.USER_NOT_EXISTED;
throw new ServiceException(OAuthStatus.USER_NOT_EXISTED);
}
String oldpwd = account.getPassword();
password = encryptPassword(password);
if (password != null && password.equals(oldpwd)) {
try {
accountService.resetAccountPwd(account.getUid(), newPassword);
accountService.delNickPasswordCache(account.getErbanNo());
//记录最近30天内绑定手机号
jedisService.setex(RedisKey.modify_pwd_sign.getKey(String.valueOf(account.getUid())),
30 * 24 * 60 *60, String.valueOf(new Date().getTime()));
return OAuthStatus.SUCCESS;
} catch (Exception e) {
return OAuthStatus.INVALID_SERVICE;
}
} else {
return OAuthStatus.OLD_PASSWORD_ERROR;
String oldPwd = account.getPassword();
password = encryptPassword(password);
if (!StringUtils.hasText(password) || password.equals(oldPwd)){
throw new ServiceException(OAuthStatus.OLD_PASSWORD_ERROR);
}
accountService.resetAccountPwd(account.getUid(), newPassword);
accountService.delNickPasswordCache(account.getErbanNo());
//记录最近30天内绑定手机号
jedisService.setex(RedisKey.modify_pwd_sign.getKey(String.valueOf(account.getUid())),
30 * 24 * 60 *60, String.valueOf(new Date().getTime()));
}
/**
@@ -371,26 +380,21 @@ public class AccountManageService {
* @param password
* @return
*/
public OAuthStatus setupInitialPassword(Long uid, String password) {
public void setupInitialPassword(Long uid, String password) {
Account account = accountService.getById(uid);
if (account == null) {
return OAuthStatus.INVALID_USER;
throw new ServiceException(OAuthStatus.INVALID_USER);
}
try {
Boolean result = accountService.updateAccountPwd(account.getUid(), password);
if (!result){
return OAuthStatus.INVALID_REQUEST;
}
// 更新用户缓存
this.jedisService.hdel(RedisKey.user.getKey(), account.getUid().toString());
this.jedisService.hdel(RedisKey.user_summary.getKey(), account.getUid().toString());
accountService.delNickPasswordCache(account.getErbanNo());
return OAuthStatus.SUCCESS;
} catch (Exception e) {
return OAuthStatus.INVALID_SERVICE;
Boolean result = accountService.updateAccountPwd(account.getUid(), password);
if (!result){
throw new ServiceException(OAuthStatus.INVALID_REQUEST);
}
// 更新用户缓存
this.jedisService.hdel(RedisKey.user.getKey(), account.getUid().toString());
this.jedisService.hdel(RedisKey.user_summary.getKey(), account.getUid().toString());
accountService.delNickPasswordCache(account.getErbanNo());
}
/**

View File

@@ -1,86 +0,0 @@
package com.accompany.oauth2.config;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
/**
* 验证码配置
*
*/
@Configuration
public class CaptchaConfig
{
@Bean(name = "captchaProducer")
public DefaultKaptcha getKaptchaBean()
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yesno
properties.setProperty("kaptcha.border", "yes");
// 边框颜色 默认为Color.BLACK
properties.setProperty("kaptcha.border.color", "105,179,90");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty("kaptcha.textproducer.font.color", "blue");
// 验证码图片宽度 默认为200
properties.setProperty("kaptcha.image.width", "160");
// 验证码图片高度 默认为50
properties.setProperty("kaptcha.image.height", "60");
// 验证码文本字符大小 默认为40
properties.setProperty("kaptcha.textproducer.font.size", "30");
// KAPTCHA_SESSION_KEY
properties.setProperty("kaptcha.session.key", "kaptchaCode");
// 验证码文本字符间距 默认为2
properties.setProperty("kaptcha.textproducer.char.space", "3");
// 验证码文本字符长度 默认为5
properties.setProperty("kaptcha.textproducer.char.length", "5");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");
// 验证码噪点颜色 默认为Color.BLACK
properties.setProperty("kaptcha.noise.color", "white");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
@Bean(name = "captchaProducerMath")
public DefaultKaptcha getKaptchaBeanMath()
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yesno
properties.setProperty("kaptcha.border", "yes");
// 边框颜色 默认为Color.BLACK
properties.setProperty("kaptcha.border.color", "105,179,90");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty("kaptcha.textproducer.font.color", "blue");
// 验证码图片宽度 默认为200
properties.setProperty("kaptcha.image.width", "160");
// 验证码图片高度 默认为50
properties.setProperty("kaptcha.image.height", "50");
// 验证码文本字符大小 默认为40
properties.setProperty("kaptcha.textproducer.font.size", "35");
// KAPTCHA_SESSION_KEY
properties.setProperty("kaptcha.session.key", "kaptchaCodeMath");
// 验证码文本生成器
properties.setProperty("kaptcha.textproducer.impl", "com.accompany.oauth2.config.KaptchaTextCreator");
// 验证码文本字符间距 默认为2
properties.setProperty("kaptcha.textproducer.char.space", "3");
// 验证码文本字符长度 默认为5
properties.setProperty("kaptcha.textproducer.char.length", "6");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");
// 验证码噪点颜色 默认为Color.BLACK
properties.setProperty("kaptcha.noise.color", "white");
// 干扰实现类
properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.WaterRipple");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}

View File

@@ -1,76 +0,0 @@
package com.accompany.oauth2.config;
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
import java.util.Random;
/**
* 验证码文本生成器
*
* @author
*/
public class KaptchaTextCreator extends DefaultTextCreator
{
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
@Override
public String getText()
{
Integer result = 0;
Random random = new Random();
int x = random.nextInt(10);
int y = random.nextInt(10);
StringBuilder suChinese = new StringBuilder();
int randomoperands = (int) Math.round(Math.random() * 2);
if (randomoperands == 0)
{
result = x * y;
suChinese.append(CNUMBERS[x]);
suChinese.append("*");
suChinese.append(CNUMBERS[y]);
}
else if (randomoperands == 1)
{
if (!(x == 0) && y % x == 0)
{
result = y / x;
suChinese.append(CNUMBERS[y]);
suChinese.append("/");
suChinese.append(CNUMBERS[x]);
}
else
{
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
}
else if (randomoperands == 2)
{
if (x >= y)
{
result = x - y;
suChinese.append(CNUMBERS[x]);
suChinese.append("-");
suChinese.append(CNUMBERS[y]);
}
else
{
result = y - x;
suChinese.append(CNUMBERS[y]);
suChinese.append("-");
suChinese.append(CNUMBERS[x]);
}
}
else
{
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
suChinese.append("=?@" + result);
return suChinese.toString();
}
}

View File

@@ -6,7 +6,6 @@ package com.accompany.oauth2.config;
* @Date 2019-01-25 02:01
*/
import com.accompany.oauth2.interceptor.FusingInterceptor;
import com.accompany.oauth2.interceptor.LoginInterceptor;
import com.accompany.oauth2.interceptor.SecurityInterceptor;
import org.springframework.context.annotation.Bean;
@@ -31,21 +30,14 @@ public class WebMvcConfig implements WebMvcConfigurer{
return new LoginInterceptor();
}
@Bean
public FusingInterceptor getFusingInterceptor() {
return new FusingInterceptor();
}
/**
* 添加拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(getRiskManagerInterceptor());
registry.addInterceptor(getSecurityInterceptor());
registry.addInterceptor(getLoginInterceptor());
registry.addInterceptor(getFusingInterceptor());
}
}

View File

@@ -1,42 +1,26 @@
package com.accompany.oauth2.controller;
import com.accompany.common.annotation.Authorization;
import com.accompany.common.constant.AppEnum;
import com.accompany.common.constant.Constant;
import com.accompany.common.device.DeviceInfo;
import com.accompany.common.exception.BusinessException;
import com.accompany.common.redis.RedisKey;
import com.accompany.common.result.BusiResult;
import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.*;
import com.accompany.core.exception.ServiceException;
import com.accompany.core.model.Account;
import com.accompany.core.service.SysConfService;
import com.accompany.core.service.account.AccountService;
import com.accompany.core.service.common.JedisLockService;
import com.accompany.core.service.common.JedisService;
import com.accompany.core.util.JwtUtils;
import com.accompany.core.util.KeyStore;
import com.accompany.core.vo.VisitorVo;
import com.accompany.oauth2.common.BaseController;
import com.accompany.oauth2.config.OAuthConfig;
import com.accompany.oauth2.constant.LoginTypeEnum;
import com.accompany.oauth2.constant.OAuthStatus;
import com.accompany.oauth2.model.AccountDetails;
import com.accompany.oauth2.result.ServiceRes;
import com.accompany.oauth2.service.MyUserDetailsService;
import com.accompany.oauth2.service.account.AccountManageService;
import com.google.common.collect.Maps;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
@@ -49,317 +33,35 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping("/acc")
public class AccountController extends BaseController {
private static final Logger logger = LoggerFactory.getLogger(AccountController.class);
/** 密码强度检查正则必须包括大小写字母和数字长度为6到16 */
private static final String PASSWORD_REGIX = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{6,16}$";
/** 密码强度检查正则必须包括大小写字母和数字长度为6到16 */
private static final String PASSWORD_REGIX_V2 = "^(?=.*\\d)(?=.*[a-zA-Z]).{6,16}$";
@Autowired
private SysConfService sysConfService;
@Autowired
private AccountService accountService;
@Autowired
private JwtUtils jwtUtils;
@Autowired
private OAuthConfig oAuthConfig;
@Autowired
private JedisService jedisService;
@Autowired
private JedisLockService jedisLockService;
@Autowired
private AuthorizationServerTokenServices tokenService;
@Autowired
private AccountManageService accountManageService;
@Autowired
private MyUserDetailsService myUserDetailsService;
/**
* 通过手机号码注册
*
* @param phone
* @param password
* @param smsCode
* @return
*/
@Deprecated
@RequestMapping(value = "signup", method = RequestMethod.POST)
@PostMapping("/logout")
@ResponseBody
public BusiResult<Void> signUp(String phone, @RequestParam String password,
String smsCode, DeviceInfo deviceInfo, HttpServletRequest request, String token,
Double gpsLongitude, Double gpsLatitude) {
String closeSwitch = jedisService.get(RedisKey.close_signup_switch.getKey());
if(StringUtils.isNotBlank(closeSwitch)){
return new BusiResult<>(OAuthStatus.CLOSE_SIGNUP_ERROR.value(), OAuthStatus.CLOSE_SIGNUP_ERROR.getReasonPhrase(), null);
public ServiceRes<Void> logout(@RequestParam("accessToken")String token) {
if (StringUtils.isBlank(token)) {
return new ServiceRes<>(OAuthStatus.INVALID_REQUEST);
}
// 加入密码DES解密
try {
password = DESUtils.DESAndBase64Decrypt(password, KeyStore.DES_ENCRYPT_KEY);
} catch (Exception e) {
throw new BadCredentialsException("password illegal.");
}
// 弱密码检查
if(!password.matches(PASSWORD_REGIX_V2)){
return new BusiResult<>(OAuthStatus.WEAK_PASSWORD.value(), OAuthStatus.WEAK_PASSWORD.getReasonPhrase(), null);
}
////检验验证码
//boolean check = accountService.verifySmsCodeByCache(phone, smsCode,null);
//if (!check) {
// return new BusiResult(OAuthStatus.INVALID_IDENTIFYING_CODE.value(), OAuthStatus.INVALID_IDENTIFYING_CODE.getReasonPhrase(), null);
//}
//校验手机号是否已经被注册
boolean exist = accountService.checkPhoneExists(phone);
if (exist) {
return new BusiResult<>(OAuthStatus.USER_HAS_SIGNED_UP.value(), "手機號碼已經被註冊,請直接登錄!", null);
}
return new BusiResult<>(BusiStatus.SUCCESS);
myUserDetailsService.logout(token);
return new ServiceRes<>(OAuthStatus.SUCCESS);
}
/**
* 通过手机号码注册
*
* @param phone
* @param password
* @param smsCode
* @return
*/
@RequestMapping(value = "/register", method = RequestMethod.POST)
@ResponseBody
public BusiResult<Account> register(String phone, @RequestParam String password, String smsCode,
String verifyCode, DeviceInfo deviceInfo, HttpServletRequest request, String token,
Double gpsLongitude, Double gpsLatitude, String phoneAreaCode) {
phone = decryptSensitiveInfo(request, phone);
String ipAddress = IPUtils.getRealIpAddress(request);
accountManageService.checkSystemBlock(phone, deviceInfo.getDeviceId(), ipAddress);
// 加入密码DES解密
try {
password = DESUtils.DESAndBase64Decrypt(password, KeyStore.DES_ENCRYPT_KEY);
} catch (Exception e) {
throw new BadCredentialsException("password illegal.");
}
// 弱密码检查
if(!password.matches(PASSWORD_REGIX_V2)){
return new BusiResult<>(OAuthStatus.WEAK_PASSWORD.value(), OAuthStatus.WEAK_PASSWORD.getReasonPhrase(), null);
}
boolean captchaSwitch = sysConfService.getCaptchaSwitch();
if(captchaSwitch){
String registerCode = jedisService.get(RedisKey.register_code.getKey(phone));
logger.info("register failed,phone:{},smsCode:{},verifyCode:{},registerCode:{},deviceInfo:{}",
phone,smsCode,verifyCode,registerCode,deviceInfo);
if(StringUtils.isBlank(registerCode) || !registerCode.equals(verifyCode)){
return new BusiResult<>(OAuthStatus.VERIFY_CODE_ERROR.value(), OAuthStatus.VERIFY_CODE_ERROR.getReasonPhrase(), null);
}
}
////检验验证码
//boolean check = accountService.verifySmsCodeByCache(phone, smsCode,null);
//if (!check) {
// return new BusiResult(OAuthStatus.INVALID_IDENTIFYING_CODE.value(), OAuthStatus.INVALID_IDENTIFYING_CODE.getReasonPhrase(), null);
//}
final String locKey = RedisKey.lock_register_by_phone.getKey(phone);
final String lockVal = jedisLockService.lock(locKey, 10 * 1000);
try {
if (BlankUtil.isBlank(lockVal)){
return new BusiResult<>(BusiStatus.REQUEST_FAST);
}
//校验手机号是否已经被注册
boolean exist = accountService.checkPhoneExists(phone);
if (exist) {
return new BusiResult<>(OAuthStatus.USER_HAS_SIGNED_UP.value(), "手机号码已经被注册,请直接登录!", null);
}
if (!CommonUtil.checkPhoneFormat(phoneAreaCode,phone)){
throw new ServiceException(BusiStatus.PHONEINVALID);
}
return new BusiResult<>(accountManageService.
saveSignUpByPhone(phone, password, deviceInfo, ipAddress,phoneAreaCode));
} catch (Exception e) {
logger.error("注册失败当前注册手机号码phone=" + phone + "失败原因:" + e.getMessage());
return new BusiResult<>(BusiStatus.SERVER_BUSY);
} finally {
jedisLockService.unlock(locKey, lockVal);
}
}
@RequestMapping(value = "getvisitor", method = RequestMethod.GET)
@ResponseBody
public BusiResult<VisitorVo> getVisitorAccount() {
try {
VisitorVo vo = accountManageService.genVisitorAccount();
return new BusiResult<>(vo);
} catch (Exception e) {
throw new BusinessException(e);
}
}
@RequestMapping(value = "logout", method = RequestMethod.POST)
@ResponseBody
public Object logout(String access_token) {
if (StringUtils.isBlank(access_token)) {
return new ServiceRes(OAuthStatus.INVALID_REQUEST);
}
myUserDetailsService.logout(access_token);
return new ServiceRes(OAuthStatus.SUCCESS);
}
@RequestMapping(value = "h5/logout", method = RequestMethod.POST)
@ResponseBody
public BusiResult<Void> h5Logout(Long uid, String token) {
try {
Claims claims = jwtUtils.parseJWT(token);
String uidStr = claims.get("uid") + "";
jedisService.hdel(RedisKey.h5loginjwtoken.getKey(), uidStr);
} catch (ExpiredJwtException e) {
logger.error("jwttoken is expired,uid={},token={}", uid, token, e);
return new BusiResult<>(406, "expired", null);
} catch (SignatureException e) {
logger.error("signature is illegal,uid={},token={}", uid, token, e);
return new BusiResult<>(407, "illegal", null);
} catch (Exception e) {
logger.error("log out error,uid={},token={}", uid, token, e);
return new BusiResult<>(BusiStatus.BUSIERROR);
}
return new BusiResult<>(BusiStatus.SUCCESS);
}
/**
* 重置密码接口,用于用户忘记密码,找回密码服务
*
* @param newPwd
* 新密码
* @param smsCode
* 重置码
* @return 1:成功 2重置码无效 3不存在该用户 4其它错误
*/
@ResponseBody
@RequestMapping(value = "pwd/reset", method = RequestMethod.POST)
public Object resetPassword(String phone, @RequestParam String newPwd,
@RequestParam String smsCode, @RequestHeader(value="pub_uid", required = false) Long uid,
HttpServletRequest request) {
phone = decryptSensitiveInfo(request, phone);
// 加入密码DES解密
try {
newPwd = DESUtils.DESAndBase64Decrypt(newPwd, KeyStore.DES_ENCRYPT_KEY);
} catch (Exception e) {
throw new BadCredentialsException("password illegal.");
}
// 密码长度检查
if(!newPwd.matches(PASSWORD_REGIX_V2)){
return new ServiceRes(OAuthStatus.WEAK_PASSWORD);
}
if (phone != null) {
if (phone.contains("*")) {
Account account = accountService.getById(uid);
if (account == null) {
return new ServiceRes(OAuthStatus.USER_NOT_EXISTED);
}
phone = account.getPhone();
if (!CommonUtil.checkPhoneFormat(account.getPhoneAreaCode(),account.getPhone())) {
return OAuthStatus.ACCOUNT_NOT_BIND_PHONE;
}
}
int count = accountService.countByPhone(phone);
if(count > 1) {
return new ServiceRes(OAuthStatus.PHONE_BIND_TOO_MANY_ACCOUNT);
}
}
OAuthStatus status;
try {
status = accountManageService.resetPasswordByResetCode(uid,phone, newPwd, smsCode);
} catch (Exception e) {
status = OAuthStatus.INVALID_SERVICE;
}
return new ServiceRes(status);
}
/**
* 设置新密码
* @param uid
* @param newPwd
* @return
*/
@Authorization
@ResponseBody
@RequestMapping(value = "pwd/set", method = RequestMethod.POST)
public Object setupPassword(@RequestParam String newPwd, @RequestHeader("pub_uid") Long uid) {
//加入密码DES解密
try {
newPwd = DESUtils.DESAndBase64Decrypt(newPwd, KeyStore.DES_ENCRYPT_KEY);
} catch (Exception e) {
throw new BadCredentialsException("password illegal.");
}
// 密码长度检查
if(!newPwd.matches(PASSWORD_REGIX_V2)){
return new ServiceRes(OAuthStatus.WEAK_PASSWORD);
}
OAuthStatus status;
try {
status = accountManageService.setupInitialPassword(uid, newPwd);
} catch (Exception e) {
logger.error("reset password error, uid:{},msg:{}", uid, e);
status = OAuthStatus.INVALID_SERVICE;
}
return new ServiceRes(status);
}
@Authorization
@ResponseBody
@RequestMapping(value = "pwd/modify", method = RequestMethod.POST)
public Object modifyPassword(@RequestParam String pwd, @RequestParam String newPwd, @RequestHeader("pub_uid") Long uid) {
// 加入密码DES解密
try {
pwd = DESUtils.DESAndBase64Decrypt(pwd, KeyStore.DES_ENCRYPT_KEY);
newPwd = DESUtils.DESAndBase64Decrypt(newPwd, KeyStore.DES_ENCRYPT_KEY);
} catch (Exception e) {
throw new BadCredentialsException("password illegal.");
}
// 密码长度检查
if(!newPwd.matches(PASSWORD_REGIX_V2)){
return new ServiceRes(OAuthStatus.WEAK_PASSWORD);
}
Account account = this.accountService.getById(uid);
if (account == null) {
return new ServiceRes(OAuthStatus.INVALID_USER);
}
OAuthStatus status;
try {
status = accountManageService.resetPasswordByOldPassword(account.getPhone(), pwd, newPwd);
} catch (Exception e) {
logger.error("reset password error, phone:{},msg:{}", account.getPhone(), e);
status = OAuthStatus.INVALID_SERVICE;
}
return new ServiceRes(status);
}
@RequestMapping("third/login")
@RequestMapping("/third/login")
public ResponseEntity<OAuth2AccessToken> login(HttpServletRequest request, String openid, Integer type, DeviceInfo deviceInfo,
AppEnum app) throws Exception {
String unionId = request.getParameter("unionid");
logger.info("/acc/third/login? app {} , type {}, unionId {}", app, type, unionId);
log.info("/acc/third/login? app {} , type {}, unionId {}", app, type, unionId);
checkAppVersion(deviceInfo);
if (StringUtils.isEmpty(openid) || type == 0) {
throw new RuntimeException("参数异常");
@@ -392,55 +94,6 @@ public class AccountController extends BaseController {
return new ResponseEntity<>(accessToken, headers, HttpStatus.OK);
}
private class ServiceRes {
private int code;
private String message;
private Object data;
public ServiceRes(OAuthStatus status) {
this(status, null);
}
public ServiceRes(OAuthStatus status, Object data) {
this.code = status.value();
this.message = status.getReasonPhrase();
this.data = data;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
public Object getData() {
return data;
}
}
/**
* @description 根据耳伴号密码获取uid
* @author qiudonglin
* @date 2020/3/9/0009
*/
@RequestMapping(value = "/getUidByUsername", method = RequestMethod.POST)
@ResponseBody
public BusiResult<Long> getUidByNickAndPassword(Long username, String password) {
if (username == null || StringUtils.isEmpty(password)) {
return new BusiResult<>(BusiStatus.ALERT_PARAMETER_ILLEGAL);
}
Long uid = accountService.getUidByNickAndPassword(username, password);
if (uid.equals(0L)) {
return new BusiResult<>(BusiStatus.ERBAN_NO_NOT_EXIST);
}
if (uid.equals(-1L)) {
return new BusiResult<>(BusiStatus.PASSWORD_ERROR);
}
return new BusiResult<>(uid);
}
private void checkAppVersion(DeviceInfo deviceInfo) {
String limitAppVersion = sysConfService.getDefaultSysConfValueById(Constant.SysConfId.APP_VERSION_LIMIT, Constant.LOWEST_VERSION_FOR_USE);
if (deviceInfo.getAppVersion() == null || AppVersionUtil.compareVersion(deviceInfo.getAppVersion(), limitAppVersion) < 0) {

View File

@@ -1,106 +0,0 @@
package com.accompany.oauth2.controller;
import com.accompany.common.redis.RedisKey;
import com.accompany.core.service.common.JedisService;
import com.accompany.oauth2.common.BaseController;
import com.alibaba.nacos.common.util.Md5Utils;
import com.google.code.kaptcha.Producer;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
/**
* 图片验证码(支持算术形式)
*/
@Controller
@RequestMapping("/acc")
public class CaptchaController extends BaseController {
private static final Logger logger = LoggerFactory.getLogger(CaptchaController.class);
@Autowired
private JedisService jedisService;
@Resource(name = "captchaProducer")
private Producer captchaProducer;
@Resource(name = "captchaProducerMath")
private Producer captchaProducerMath;
/**
* 验证码生成
*/
@RequestMapping(value = "/captcha/image")
public ModelAndView getKaptchaImage(@RequestParam String phone,@RequestParam long timestamp,@RequestParam String nonce,
@RequestParam String sign, HttpServletRequest request, HttpServletResponse response) {
phone = decryptSensitiveInfo(request, phone);
String result = phone+nonce+timestamp;
String genSign = Md5Utils.getMD5(result,"UTF8");
if(!sign.equals(genSign)){
logger.error("captcha sign error,genSign:{},result:{},sign:{}",genSign,result,sign);
return null;
}
Long currentTime = System.currentTimeMillis();
String timeSwitch = jedisService.get(RedisKey.register_time_switch.getKey());
if(StringUtils.isBlank(timeSwitch)){
if(currentTime - timestamp > 60 * 1000){//误差超过60秒不给请求。
logger.error("captcha replay attacks currentTime:{},timestamp:{},phone:{},",currentTime,timestamp,phone);
return null;
}
}
ServletOutputStream out = null;
try {
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
response.setHeader("Pragma", "no-cache");
response.setContentType("image/jpeg");
String type = request.getParameter("type");
String capStr = null;
String code = null;
BufferedImage bi = null;
if ("char".equals(type)) {
capStr = code = captchaProducer.createText();
bi = captchaProducer.createImage(capStr);
} else if ("math".equals(type) || StringUtils.isBlank(type)) {
String capText = captchaProducerMath.createText();
capStr = capText.substring(0, capText.lastIndexOf("@"));
code = capText.substring(capText.lastIndexOf("@") + 1);
bi = captchaProducerMath.createImage(capStr);
}
jedisService.set(RedisKey.register_code.getKey(phone),code,600);
out = response.getOutputStream();
ImageIO.write(bi, "jpg", out);
out.flush();
} catch (Exception e) {
logger.error("error message,",e);
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}

View File

@@ -127,26 +127,6 @@ public class H5LoginController extends BaseController {
return new BusiResult<>(accountH5LoginService.smsLogin(mobile, code));
}
/**
* 注册
*
* @param phoneAreaCode
* @param mobile
* @param code
* @param inviteCode
* @param inviteUid
* @param request
* @return
*/
@PostMapping("/register")
public BusiResult<Void> registerByPhone(String phoneAreaCode, String mobile, String code, String inviteCode, Long inviteUid, HttpServletRequest request) {
log.info("h5 registerByPhone, mobile:{}, code:{}, inviteCode: {}", mobile, code, inviteCode);
DeviceInfo deviceInfo = getDeviceInfo(request);
String ipAddress = IPUtils.getRealIpAddress(request);
accountH5LoginService.register(mobile, code, inviteCode, inviteUid, deviceInfo, ipAddress, phoneAreaCode);
return new BusiResult<>(BusiStatus.SUCCESS);
}
/**
* 授权登录
*

View File

@@ -0,0 +1,120 @@
package com.accompany.oauth2.controller;
import com.accompany.common.annotation.Authorization;
import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.DESUtils;
import com.accompany.core.exception.ServiceException;
import com.accompany.core.model.Account;
import com.accompany.core.service.account.AccountService;
import com.accompany.core.util.KeyStore;
import com.accompany.oauth2.common.BaseController;
import com.accompany.oauth2.constant.OAuthStatus;
import com.accompany.oauth2.result.ServiceRes;
import com.accompany.oauth2.service.account.AccountManageService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@Slf4j
@RestController
@RequestMapping("/acc/pwd")
public class PwdController extends BaseController {
/** 密码强度检查正则必须包括大小写字母和数字长度为6到16 */
private static final String PASSWORD_REGIX_V2 = "^(?=.*\\d)(?=.*[a-zA-Z]).{6,16}$";
@Autowired
private AccountService accountService;
@Autowired
private AccountManageService accountManageService;
/**
* 重置密码接口,用于用户忘记密码,找回密码服务
*
* @param newPwd
* 新密码
* @param smsCode
* 重置码
* @return 1:成功 2重置码无效 3不存在该用户 4其它错误
*/
//@Authorization
@PostMapping("/reset")
@SneakyThrows
public ServiceRes<Void> resetPassword(HttpServletRequest request,
String phone, String newPwd, String smsCode) {
if (StringUtils.isBlank(phone) || StringUtils.isBlank(newPwd) || StringUtils.isBlank(smsCode)){
throw new ServiceException(BusiStatus.PARAMERROR);
}
Long uid = getUid(request);
phone = decryptSensitiveInfo(request, phone);
newPwd = DESUtils.DESAndBase64Decrypt(newPwd, KeyStore.DES_ENCRYPT_KEY);
// 密码长度检查
if(!newPwd.matches(PASSWORD_REGIX_V2)){
return new ServiceRes<>(OAuthStatus.WEAK_PASSWORD);
}
accountManageService.resetPasswordByResetCode(uid, phone, newPwd, smsCode);
return new ServiceRes<>(OAuthStatus.SUCCESS);
}
/**
* 设置新密码
* @param uid
* @param newPwd
* @return
*/
@Authorization
@PostMapping("/set")
@SneakyThrows
public ServiceRes<Void> setupPassword(HttpServletRequest request, String newPwd) {
Long uid = getUid(request);
//加入密码DES解密
newPwd = DESUtils.DESAndBase64Decrypt(newPwd, KeyStore.DES_ENCRYPT_KEY);
// 密码长度检查
if(!newPwd.matches(PASSWORD_REGIX_V2)){
return new ServiceRes<>(OAuthStatus.WEAK_PASSWORD);
}
accountManageService.setupInitialPassword(uid, newPwd);
return new ServiceRes<>(OAuthStatus.SUCCESS);
}
@Authorization
@PostMapping("/modify")
@SneakyThrows
public ServiceRes<Void> modifyPassword(HttpServletRequest request,
String pwd, String newPwd) {
Long uid = getUid(request);
// 加入密码DES解密
pwd = DESUtils.DESAndBase64Decrypt(pwd, KeyStore.DES_ENCRYPT_KEY);
newPwd = DESUtils.DESAndBase64Decrypt(newPwd, KeyStore.DES_ENCRYPT_KEY);
// 密码长度检查
if(!newPwd.matches(PASSWORD_REGIX_V2)){
return new ServiceRes<>(OAuthStatus.WEAK_PASSWORD);
}
Account account = this.accountService.getById(uid);
if (account == null) {
return new ServiceRes<>(OAuthStatus.INVALID_USER);
}
accountManageService.resetPasswordByOldPassword(account.getPhone(), pwd, newPwd);
return new ServiceRes<>(OAuthStatus.SUCCESS);
}
}

View File

@@ -16,9 +16,8 @@ import com.accompany.oauth2.vo.TicketRes;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -29,9 +28,9 @@ import java.util.Map;
* @author liuguofu
* on 3/17/15.
*/
@Controller
@RequestMapping("/oauth")
@Slf4j
@RestController
@RequestMapping("/oauth")
public class TicketController extends BaseController {
@Autowired
@@ -39,8 +38,7 @@ public class TicketController extends BaseController {
@Autowired
private SysConfService sysConfService;
@RequestMapping("ticket")
@ResponseBody
@RequestMapping("/ticket")
public Object issueTicket(String issue_type, String access_token, HttpServletRequest request,
HttpServletResponse response, DeviceInfo deviceInfo) {
log.info("oauth/ticket=" + access_token + ".........");
@@ -74,7 +72,6 @@ public class TicketController extends BaseController {
}
private void checkAppVersion(DeviceInfo deviceInfo) {
String client = deviceInfo.getClient();
String limitAppVersion = sysConfService.getDefaultSysConfValueById(Constant.SysConfId.APP_VERSION_LIMIT, Constant.LOWEST_VERSION_FOR_USE);
if (deviceInfo.getAppVersion() == null || AppVersionUtil.compareVersion(deviceInfo.getAppVersion(), limitAppVersion) < 0) {
throw new ServiceException(BusiStatus.VERSIONTOOOLD);

View File

@@ -1,49 +0,0 @@
package com.accompany.oauth2.interceptor;
import com.accompany.common.redis.RedisKey;
import com.accompany.common.utils.StringUtils;
import com.accompany.core.service.common.JedisService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author yangziwen
* @description 根据配置动态熔断服务
* @date 2018/6/22 00:49
*/
public class FusingInterceptor extends BasicInterceptor {
private static final Logger logger = LoggerFactory.getLogger(FusingInterceptor.class);
@Autowired
private JedisService jedisService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
String cache = this.jedisService.hget(RedisKey.stop_service.getKey(), request.getRequestURI());
if (StringUtils.isNotEmpty(cache)) {
logger.warn("{} has been fusing", request.getRequestURI());
this.writeResponse(response, 503, "service suspend");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView)
throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}

View File

@@ -1,62 +0,0 @@
package com.accompany.oauth2.interceptor;
import com.accompany.common.constant.ApplicationConstant;
import com.accompany.core.service.common.JedisService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author yubin
* @Description 风控拦截器 todo 优化
* 1.处理昵称敏感词
* @Date 2019-07-05 10:15
*/
public class RiskManagerInterceptor extends BasicInterceptor{
private static final Logger logger = LoggerFactory.getLogger(RiskManagerInterceptor.class);
@Autowired
private JedisService jedisService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
// String uid = this.getUid(request);
// if (StringUtils.isEmpty(uid) || StringUtils.equalsIgnoreCase(uid, "null") || !StringUtils.isNumeric(uid)) {
// logger.warn("uid illegal, uri={}, uid={}", request.getRequestURI(), uid);
// writeResponse(response, 401, "need login!");
// return false;
// }
//
// if (this.jedisService.sismember(RedisKey.global_block_uid.getKey(), uid)){
// logger.warn("uid 昵称敏感 {} 被封禁,不允许访问", uid);
// return false;
// }
//
return true;
}
/**
* 获取 uid 以业务参数为首选
* @param request
* @return
*/
private String getUid(HttpServletRequest request) {
String uidStr = request.getParameter(ApplicationConstant.PublicParameters.UID);
if (StringUtils.isEmpty(uidStr)) {
uidStr = request.getHeader(ApplicationConstant.PublicParameters.PUB_UID);
}
return uidStr;
}
}