提交 9976c140 authored 作者: huyufan's avatar huyufan

交易密码相关

上级 c0a062a8
......@@ -103,11 +103,12 @@ public enum PerformanceResultEnum implements ResultEnum {
MOBILE_IS_EMPTY(1901, "用户手机号不能为空"),
CAPTCHA_IS_EMPTY(1902, "验证码不能为空"),
USER_ACCOUNT_NOT_FOUND(1903, "用户账号未找到"),
CAPTCHA_IS_EXPIRE(1904, "验证码已失效,请重新发送"),
CAPTCHA_IS_EXPIRE(1904, "短信验证码已失效,请重新发送"),
CAPTCHA_MORE_COUNT(1905, "验证码发送过于频繁,请稍后再发"),
CAPTCHA_IS_FAIL(1906, "验证码错误"),
BUSINESS_NO_FAIL(1907, "营业执照校验不一致,请重新输入"),
TOKEN_IS_FAIL(1908, "token失效,请重新获取token"),
PASSWORD_RESET_IS_FAIL(1909, "重置密码出现异常"),
;
private final int code;
......
......@@ -8,13 +8,12 @@ import javax.validation.constraints.NotBlank;
@Data
public class ResetPasswordParam {
@ApiModelProperty(value = "营业执照编号", example = "1")
@NotBlank(message = "营业执照编号")
private String businessLicenseNumber;
@ApiModelProperty(value = "交易密码", example = "1")
@NotBlank(message = "交易密码")
private String password;
@ApiModelProperty(value = "验证手机号通过后Token", example = "1")
@NotBlank(message = "验证手机号通过后Token")
@ApiModelProperty(value = "验证营业执照后通过后Token", example = "1")
@NotBlank(message = "验证营业执照后通过后Token")
private String token;
@ApiModelProperty(value = "手机号", example = "1")
......
......@@ -6,6 +6,7 @@ import com.clx.performance.constant.RedisConstants;
import com.clx.performance.enums.PerformanceResultEnum;
import com.clx.performance.param.app.CheckMobileParam;
import com.clx.performance.param.app.InformationParam;
import com.clx.performance.param.app.ResetPasswordParam;
import com.msl.common.exception.ServiceSystemException;
import com.msl.common.result.Result;
import org.apache.commons.lang3.StringUtils;
......@@ -15,14 +16,10 @@ import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
......@@ -44,52 +41,58 @@ public class ResetPasswordAnnotationAop {
// 获取AspectAnnotation注解
ResetPassword aspectAnnotation = method.getAnnotation(ResetPassword.class);
String mobile = "";
if (aspectAnnotation.name().equals("checkMobile")) {
CheckMobileParam bean = JSONUtil.toBean(JSONUtil.parse(jp.getArgs()[0]).toString(), CheckMobileParam.class);
mobile = JSONUtil.parse(jp.getArgs()[0]).getByPath("mobile").toString();
String token = bean.getToken();
String redisVal = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile);
if (!StringUtils.equals(token, redisVal)) {
throw new RuntimeException("抛异常");
}
} else if (aspectAnnotation.name().equals("sendMobileCaptcha")) {
mobile = JSONUtil.parse(jp.getArgs()[0]).getByPath("mobile").toString();
String content = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_CAPTCHA_ID + mobile);
if (StringUtils.isNoneBlank(content)) {
String token = UUID.randomUUID().toString();
redisTemplate.opsForValue().set(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile, token);
redisTemplate.expire(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile, 60, TimeUnit.SECONDS);
return token;
}
String count = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_CAPTCHA_MOBILE_COUNT + mobile);
if (StringUtils.isNotBlank(content) && Integer.parseInt(count) >= 10) {
throw new ServiceSystemException(PerformanceResultEnum.CAPTCHA_MORE_COUNT);
}
} else if (aspectAnnotation.name().equals("checkBusinessLicenseNumber")) {
InformationParam bean = JSONUtil.toBean(JSONUtil.parse(jp.getArgs()[0]).toString(), InformationParam.class);
mobile = JSONUtil.parse(jp.getArgs()[0]).getByPath("mobile").toString();
String token = bean.getToken();
String redisVal = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile);
if (!StringUtils.equals(token, redisVal)) {
throw new RuntimeException("抛异常");
}
String token = "";
String redisVal = "";
switch (aspectAnnotation.name()) {
case "checkMobile":
CheckMobileParam checkMobileParam = JSONUtil.toBean(JSONUtil.parse(jp.getArgs()[0]).toString(), CheckMobileParam.class);
mobile = checkMobileParam.getMobile();
token = checkMobileParam.getToken();
redisVal = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile);
if (!StringUtils.equals(token, redisVal)) {
throw new ServiceSystemException(PerformanceResultEnum.TOKEN_IS_FAIL);
}
break;
case "sendMobileCaptcha":
mobile = JSONUtil.parse(jp.getArgs()[0]).getByPath("mobile").toString();
String content = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_MOBILE_CAPTCHA + mobile);
if (StringUtils.isNoneBlank(content)) {
token = UUID.randomUUID().toString();
redisTemplate.opsForValue().set(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile, token);
redisTemplate.expire(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile, 60, TimeUnit.SECONDS);
return Result.ok(token);
}
break;
case "checkBusinessLicenseNumber":
InformationParam informationParam = JSONUtil.toBean(JSONUtil.parse(jp.getArgs()[0]).toString(), InformationParam.class);
mobile = informationParam.getMobile();
token = informationParam.getToken();
redisVal = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile);
if (!StringUtils.equals(token, redisVal)) {
throw new ServiceSystemException(PerformanceResultEnum.TOKEN_IS_FAIL);
}
break;
case "resetPassword":
ResetPasswordParam resetPasswordParam = JSONUtil.toBean(JSONUtil.parse(jp.getArgs()[0]).toString(), ResetPasswordParam.class);
mobile = resetPasswordParam.getMobile();
token = resetPasswordParam.getToken();
redisVal = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile);
if (!StringUtils.equals(token, redisVal)) {
throw new ServiceSystemException(PerformanceResultEnum.TOKEN_IS_FAIL);
}
break;
default:
throw new RuntimeException();
}
//执行方法前
Object returnVal = null;
returnVal = jp.proceed();
Result result = JSONUtil.toBean(JSONUtil.parse(returnVal).toString(), Result.class);
if (aspectAnnotation.name().equals("sendMobileCaptcha")) {
//执行方法后
redisTemplate.opsForValue().increment(RedisConstants.MESSAGE_CAPTCHA_MOBILE_COUNT + mobile);
redisTemplate.expire(RedisConstants.MESSAGE_CAPTCHA_MOBILE_COUNT + mobile, 60, TimeUnit.SECONDS);
}
redisTemplate.opsForValue().set(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile, result.getData().toString());
redisTemplate.expire(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile, 60, TimeUnit.SECONDS);
......@@ -97,18 +100,4 @@ public class ResetPasswordAnnotationAop {
return returnVal;
}
private static Map<String, Object> getFieldsName(ProceedingJoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
String[] parameterNames = pnd.getParameterNames(method);
Map<String, Object> paramMap = new HashMap<>(8);
for (int i = 0; i < parameterNames.length; i++) {
paramMap.put(parameterNames[i], args[i]);
}
return paramMap;
}
}
......@@ -32,9 +32,8 @@ public class RedisConstants {
*/
public static final String ID_SNOWFLAKE = "clx-performance:idsnowflake";
public static final String MESSAGE_CAPTCHA_ID = "message:expire:";
public static final String MESSAGE_MOBILE_CAPTCHA = "message:mobile:captcha:";
public static final String MESSAGE_CAPTCHA_MOBILE_COUNT = "message:mobile:count:";
public static final String MESSAGE_RESET_PASSWORD_TOKEN = "message:resetpassword:token:";
}
......@@ -42,14 +42,6 @@ public class AppOwnerAccountController {
}
@ApiOperation(value = "验证手机号验证码", notes = "<br>By:胡宇帆")
@PostMapping("/checkMobile")
@ResetPassword(name = "checkMobile")
public Result<String> checkMobile(@RequestBody CheckMobileParam param) {
String token = ownerAccountService.checkMobile(param);
return Result.ok(token);
}
@ApiOperation(value = "发送手机验证码", notes = "<br>By:胡宇帆")
@PostMapping("/sendMobileCaptcha")
@ResetPassword(name = "sendMobileCaptcha")
......@@ -58,6 +50,14 @@ public class AppOwnerAccountController {
return Result.ok(token);
}
@ApiOperation(value = "验证手机号验证码", notes = "<br>By:胡宇帆")
@PostMapping("/checkMobile")
@ResetPassword(name = "checkMobile")
public Result<String> checkMobile(@RequestBody CheckMobileParam param) {
String token = ownerAccountService.checkMobile(param);
return Result.ok(token);
}
@ApiOperation(value = "验证营业执照编号", notes = "<br>By:胡宇帆")
@PostMapping("/checkBusinessLicenseNumber")
@ResetPassword(name = "checkBusinessLicenseNumber")
......
package com.clx.performance.dao;
import com.clx.performance.mapper.OwnerAccountPasswordMapper;
import com.clx.performance.model.OwnerAccountPassword;
import com.msl.common.dao.BaseDao;
/**
* @author kavin
* Date 2023-11-28
* Time 17:42
*/
public interface OwnerAccountPasswordDao extends BaseDao<OwnerAccountPasswordMapper, OwnerAccountPassword, Integer> {
OwnerAccountPassword findEntityByUserNo(Long userNo);
}
package com.clx.performance.dao.impl;
import com.clx.performance.dao.OwnerAccountPasswordDao;
import com.clx.performance.mapper.OwnerAccountPasswordMapper;
import com.clx.performance.model.OwnerAccountPassword;
import com.msl.common.dao.impl.BaseDaoImpl;
import org.springframework.stereotype.Repository;
/**
* @author kavin
* Date 2023-11-28
* Time 17:42
*/
@Repository
public class OwnerAccountPasswordDaoImpl extends BaseDaoImpl<OwnerAccountPasswordMapper, OwnerAccountPassword, Integer> implements OwnerAccountPasswordDao {
@Override
public OwnerAccountPassword findEntityByUserNo(Long userNo) {
return baseMapper.selectOne(lQrWrapper().eq(OwnerAccountPassword::getUserNo, userNo));
}
}
package com.clx.performance.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.clx.performance.model.OwnerAccountPassword;
/**
* @author kavin
* Date 2023-11-28
* Time 17:42
*/
public interface OwnerAccountPasswordMapper extends BaseMapper<OwnerAccountPassword> {
}
package com.clx.performance.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.msl.common.config.KeyColumn;
import com.msl.common.model.HasKey;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* @author kavin
* Date 2023-11-28
* Time 17:42
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("owner_account_password")
@Builder
public class OwnerAccountPassword implements HasKey<Integer> {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@TableField("user_no")
@ApiModelProperty("")
private Long userNo;
@TableField("password")
@ApiModelProperty("交易密码")
private String password;
@TableField("create_time")
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@TableField("modified_time")
@ApiModelProperty("修改时间")
private LocalDateTime modifiedTime;
@Override
@KeyColumn("id")
public Integer gainKey() {
return this.id;
}
}
......@@ -28,6 +28,7 @@ import com.clx.performance.param.pc.owner.FrozenAccountParam;
import com.clx.performance.param.pc.owner.ThawAccountParam;
import com.clx.performance.service.OwnerAccountService;
import com.clx.performance.struct.OwnerAccountStruct;
import com.clx.performance.utils.MyMD5Util;
import com.clx.performance.utils.excel.ExcelData;
import com.clx.performance.utils.excel.ExcelField;
import com.clx.performance.utils.excel.ExcelSheet;
......@@ -42,7 +43,6 @@ import com.clx.user.vo.feign.OwnerInfoFeignVO;
import com.clx.user.vo.pc.owner.OwnerBindCardVO;
import com.msl.common.base.Optional;
import com.msl.common.enums.ResultCodeEnum;
import com.msl.common.enums.ResultEnum;
import com.msl.common.exception.ServiceSystemException;
import com.msl.common.result.Result;
import com.msl.user.data.UserSessionData;
......@@ -55,7 +55,9 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
......@@ -92,6 +94,8 @@ public class OwnerAccountServiceImpl implements OwnerAccountService {
private final OwnerFeign ownerFeign;
private final OwnerAccountPasswordDao ownerAccountPasswordDao;
@Override
public IPage<OwnerAccountVO> pageList(PageOwnerAccountListParam param) {
return ownerAccountDao.pageList(param);
......@@ -906,25 +910,25 @@ public class OwnerAccountServiceImpl implements OwnerAccountService {
@Override
public String checkMobile(CheckMobileParam param) {
Long userNo = TokenUtil.getLoginUserInfo().getUserNo();
if (ObjectUtil.isNull(userNo)) {
throw new ServiceSystemException(PerformanceResultEnum.USER_ID_IS_EMPTY);
}
if (StringUtils.isBlank(param.getMobile())) {
throw new ServiceSystemException(PerformanceResultEnum.MOBILE_IS_EMPTY);
}
if (StringUtils.isBlank(param.getCaptcha())) {
throw new ServiceSystemException(PerformanceResultEnum.CAPTCHA_IS_EMPTY);
}
List<OwnerAccount> accountList = ownerAccountDao.accountInfo(userNo);
if (CollectionUtil.isEmpty(accountList)) {
throw new ServiceSystemException(PerformanceResultEnum.USER_ACCOUNT_NOT_FOUND);
}
// Long userNo = TokenUtil.getLoginUserInfo().getUserNo();
// if (ObjectUtil.isNull(userNo)) {
// throw new ServiceSystemException(PerformanceResultEnum.USER_ID_IS_EMPTY);
// }
//
// if (StringUtils.isBlank(param.getMobile())) {
// throw new ServiceSystemException(PerformanceResultEnum.MOBILE_IS_EMPTY);
// }
//
// if (StringUtils.isBlank(param.getCaptcha())) {
// throw new ServiceSystemException(PerformanceResultEnum.CAPTCHA_IS_EMPTY);
// }
//
// List<OwnerAccount> accountList = ownerAccountDao.accountInfo(userNo);
// if (CollectionUtil.isEmpty(accountList)) {
// throw new ServiceSystemException(PerformanceResultEnum.USER_ACCOUNT_NOT_FOUND);
// }
String content = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_CAPTCHA_ID + param.getMobile());
String content = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_MOBILE_CAPTCHA + param.getMobile());
if (StringUtils.isBlank(content)) {
throw new ServiceSystemException(PerformanceResultEnum.CAPTCHA_IS_EXPIRE);
}
......@@ -974,6 +978,26 @@ public class OwnerAccountServiceImpl implements OwnerAccountService {
@Override
public void resetPassword(ResetPasswordParam param) {
Long userNo = TokenUtil.getLoginUserInfo().getUserNo();
String password = param.getPassword();
try {
password = MyMD5Util.getEncryptedPwd(password);
} catch (Exception e) {
throw new ServiceSystemException(PerformanceResultEnum.PASSWORD_RESET_IS_FAIL);
}
OwnerAccountPassword entity = ownerAccountPasswordDao.findEntityByUserNo(userNo);
if (null == entity) {
OwnerAccountPassword build = OwnerAccountPassword.builder().password(password).userNo(userNo).build();
ownerAccountPasswordDao.saveEntity(build);
} else {
OwnerAccountPassword build = OwnerAccountPassword.builder()
.id(entity.getId())
.password(password).userNo(userNo).build();
ownerAccountPasswordDao.updateEntityByKey(build);
}
}
public static void main(String[] args) {
}
}
package com.clx.performance.utils;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
public class MyMD5Util {
private static final String HEX_NUMS_STR = "0123456789ABCDEF";
private static final Integer SALT_LENGTH = 12;
//将16进制字符转换为字节数组
public static byte[] hexStringToByte(String hex) {
int len = (hex.length() / 2);
byte[] result = new byte[len];
char[] hexChars = hex.toCharArray();
for (int i = 0; i < len; i++) {
int pos = i * 2;
result[i] = (byte) (HEX_NUMS_STR.indexOf(hexChars[pos]) << 4 | HEX_NUMS_STR
.indexOf(hexChars[pos + 1]));
}
return result;
}
//将指定byte数组转换成16进制字符串
public static String byteToHexString(byte[] b) {
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
hexString.append(hex.toUpperCase());
}
return hexString.toString();
}
//验证口令是否合法
public static boolean validPassword(String password, String passwordInDb)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
// 将16进制字符串格式口令转换成字节数组
byte[] pwdInDb = hexStringToByte(passwordInDb);
// 声明盐变量
byte[] salt = new byte[SALT_LENGTH];
// 将盐从数据库中保存的口令字节数组中提取出来
System.arraycopy(pwdInDb, 0, salt, 0, SALT_LENGTH);
// 创建消息摘要对象
MessageDigest md = MessageDigest.getInstance("MD5");
// 将盐数据传入消息摘要对象
md.update(salt);
// 将口令的数据传给消息摘要对象
md.update(password.getBytes("UTF-8"));
// 生成输入口令的消息摘要
byte[] digest = md.digest();
// 声明一个保存数据库中口令消息摘要的变量
byte[] digestInDb = new byte[pwdInDb.length - SALT_LENGTH];
// 取得数据库中口令的消息摘要
System.arraycopy(pwdInDb, SALT_LENGTH, digestInDb, 0, digestInDb.length);
// 比较根据输入口令生成的消息摘要和数据库中消息摘要是否相同
if (Arrays.equals(digest, digestInDb)) {
// 口令正确返回口令匹配消息
return true;
} else {
// 口令不正确返回口令不匹配消息
return false;
}
}
//获得加密后的口令
public static String getEncryptedPwd(String password)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
// 声明加密后的口令数组变量
byte[] pwd = null;
// 随机数生成器
SecureRandom random = new SecureRandom();
// 声明盐数组变量
byte[] salt = new byte[SALT_LENGTH];
// 将随机数放入盐变量中
random.nextBytes(salt);
// 声明消息摘要对象
MessageDigest md = null;
// 创建消息摘要
md = MessageDigest.getInstance("MD5");
// 将盐数据传入消息摘要对象
md.update(salt);
// 将口令的数据传给消息摘要对象
md.update(password.getBytes("UTF-8"));
// 获得消息摘要的字节数组
byte[] digest = md.digest();
// 因为要在口令的字节数组中存放盐,所以加上盐的字节长度
pwd = new byte[digest.length + SALT_LENGTH];
// 将盐的字节拷贝到生成的加密口令字节数组的前12个字节,以便在验证口令时取出盐
System.arraycopy(salt, 0, pwd, 0, SALT_LENGTH);
// 将消息摘要拷贝到加密口令字节数组从第13个字节开始的字节
System.arraycopy(digest, 0, pwd, SALT_LENGTH, digest.length);
// 将字节数组格式加密后的口令转化为16进制字符串格式的口令
return byteToHexString(pwd);
}
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论