Skip to content

Commit

Permalink
Merge pull request #282 from Jzow/master
Browse files Browse the repository at this point in the history
Add email bind views and apis
  • Loading branch information
Jzow authored Dec 11, 2023
2 parents e5dad20 + f1ea372 commit 89a7502
Show file tree
Hide file tree
Showing 29 changed files with 1,057 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ public Response<String> sendSmsCode(@PathVariable Integer type, @PathVariable St
return Response.responseMsg(BaseCodeEnum.SMS_VERIFY_SEND_SUCCESS);
}

@GetMapping("email/{type}/{email}")
public Response<String> sendEmailCode(@PathVariable Integer type, @PathVariable String email) {
return commonService.sendEmailCode(type, email);
}

@PostMapping("upload/excel")
public Response<String> uploadExclsData(@RequestParam("file") MultipartFile file) {
return commonService.uploadExclsData(file);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,14 @@ public Response<String> deleteUser(@RequestParam(value = "ids") List<Long> ids)
public Response<String> resetPassword(@RequestParam(value = "id") Long id) {
return userService.resetPassword(id);
}

@PutMapping(value = "resetPhoneNumber")
public Response<String> resetPhoneNumber(@RequestBody ResetPhoneDTO resetPhoneDTO) {
return userService.resetPhoneNumber(resetPhoneDTO);
}

@PutMapping(value = "resetEmail")
public Response<String> resetEmail(@RequestBody ResetEmailDTO resetEmailDTO) {
return userService.resetEmail(resetEmailDTO);
}
}
27 changes: 27 additions & 0 deletions core/domain/src/main/java/com/wansenai/dto/user/ResetEmailDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2023-2033 WanSen AI Team, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
* with the License. A copy of the License is located at
*
* http://opensource.wansenai.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
package com.wansenai.dto.user;

import lombok.Data;

@Data
public class ResetEmailDTO {

private Long userId;

private String oldEmail;

private String email;

private String emailCode;
}
27 changes: 27 additions & 0 deletions core/domain/src/main/java/com/wansenai/dto/user/ResetPhoneDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2023-2033 WanSen AI Team, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
* with the License. A copy of the License is located at
*
* http://opensource.wansenai.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
package com.wansenai.dto.user;

import lombok.Data;

@Data
public class ResetPhoneDTO {

private Long userId;

private String oldPhoneNumber;

private String phoneNumber;

private String sms;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright 2023-2033 WanSen AI Team, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
* with the License. A copy of the License is located at
*
* http://opensource.wansenai.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
package com.wansenai.middleware.email;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.wansenai.utils.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class EmailToken {
// 3 分钟
public static final long EXPIRE_TIME = 3 * 60 * 1000;

// token_secret
public final String TOKEN_SECRET = "f26e587c28064d0e855e72c0a6a0e618";

private final RedisUtil redisUtil;

public EmailToken(RedisUtil redisUtil) {
this.redisUtil = redisUtil;
}

/**
* 根据邮件地址和用户名创建token
* 邮件地址为验签
* HMAC256算法
*
* @param email
* @param name
* @return
*/
public String createToke(String email, String name) {
try {
// 过期时间
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
// 私钥及加密算法
Algorithm algorithm = Algorithm.HMAC256(email);
// 设置头部信息
Map<String, Object> map = new HashMap<String, Object>();
map.put("typ", "JWT");
map.put("alg", "HS256");
String token = JWT.create()
.withHeader(map)
.withClaim("username", name)
.withClaim("loginEmail", email)
.withExpiresAt(date)
.sign(algorithm);
// 这里截取返回最后一段token
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(email)).build();
DecodedJWT jwt = verifier.verify(token);
log.info("Email生成的第一次:" + token);
// 保存redis
redisUtil.set("payload", jwt.getPayload());
return jwt.getSignature();
} catch (Exception e) {
return null;
}
}

/**
* 根据token和邮件地址进行解密
*
* @param token
* @param email
* @return
*/
public boolean checkToken(String token, String email) {
// 根据校验规则HMAC256生成校验对象
try {
// 组装完整token,从redis获取payload的值
String payload = redisUtil.getString("payload");
log.info("Email: Redis获取的payload" + payload);
String FullToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" + "." + payload + "." + token;
log.info("Email: token:" + token);
log.info(FullToken);
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(email)).build();
verifier.verify(FullToken);
return true;
} catch (TokenExpiredException e) {
log.error("Email: Token已经过期:" + e.getMessage());
return false;
} catch (SignatureVerificationException e) {
log.error("Email: Token不合法:" + e.getMessage());
return false;
} catch (Exception e) {
log.error("Email: Token认证失败:" + e.getMessage());
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public interface CommonService {
CaptchaVO getCaptcha();
Boolean sendSmsCode(Integer type, String phoneNumber);

Response<String> sendEmailCode(Integer type, String email);

Response<String> uploadExclsData(MultipartFile file);

File exportExcel(String type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.wansenai.utils.SnowflakeIdUtil;
import com.wansenai.utils.constants.SecurityConstants;
import com.wansenai.utils.constants.SmsConstants;
import com.wansenai.utils.email.EmailUtils;
import com.wansenai.utils.enums.*;
import com.wansenai.utils.redis.RedisUtil;
import com.wansenai.utils.response.Response;
Expand Down Expand Up @@ -179,13 +180,15 @@ public Boolean sendSmsCode(Integer type, String phoneNumber) {
case 0 -> SmsConstants.SMS_TEMPLATE_ID_REGISTER_USER;
case 1 -> SmsConstants.SMS_TEMPLATE_ID_PHONE_LOGIN;
case 2 -> SmsConstants.SMS_TEMPLATE_ID_UPDATE_PASSWORD;
case 3 -> SmsConstants.SMS_TEMPLATE_ID_UPDATE_PHONE;
default -> "";
};

var key = switch (type) {
case 0 -> SecurityConstants.REGISTER_VERIFY_CODE_CACHE_PREFIX;
case 1 -> SecurityConstants.LOGIN_VERIFY_CODE_CACHE_PREFIX;
case 2 -> SecurityConstants.UPDATE_PASSWORD_VERIFY_CODE_CACHE_PREFIX;
case 3 -> SecurityConstants.UPDATE_PHONE_VERIFY_CODE_CACHE_PREFIX;
default -> "";
};

Expand Down Expand Up @@ -222,6 +225,49 @@ public Boolean sendSmsCode(Integer type, String phoneNumber) {
}
}

public static String getForgetCode() {
Random random = new Random();
//把随机生成的数字转成字符串
String str = String.valueOf(random.nextInt(9));
for (int i = 0; i < 5; i++) {
str += random.nextInt(9);
}
return str;
}

@Override
public Response<String> sendEmailCode(Integer type, String email) {
if (!StringUtils.hasLength(email)) {
return Response.responseMsg(BaseCodeEnum.PARAMETER_NULL);
}
String resultCode = "";
if (redisUtil.hasKey(SecurityConstants.EMAIL_RESET_VERIFY_CODE_CACHE_PREFIX + email)) {
resultCode = redisUtil.getString(email + ":forget_code");
} else {
resultCode = getForgetCode();
redisUtil.set(SecurityConstants.EMAIL_RESET_VERIFY_CODE_CACHE_PREFIX + email, resultCode);
redisUtil.expire(SecurityConstants.EMAIL_RESET_VERIFY_CODE_CACHE_PREFIX + email, 180);
}

try {
switch (type)
{
case 0:
EmailUtils.forgetPasswordEmailNotice(resultCode, email);
break;
case 1:
EmailUtils.resetEmailNotice(resultCode, email);
break;
default:
break;
}
}catch (Exception e) {
log.error("邮箱验证码发送失败:" + e.getMessage());
}

return Response.responseMsg(BaseCodeEnum.EMAIL_VERIFY_SEND_SUCCESS);
}

@Override
public Response<String> uploadExclsData(MultipartFile file) {
if(!file.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,8 @@ public interface ISysUserService extends IService<SysUser> {
Response<String> resetPassword(Long id);

Response<List<UserInfoVO>> operator();

Response<String> resetPhoneNumber(ResetPhoneDTO resetPhoneDTO);

Response<String> resetEmail(ResetEmailDTO resetEmailDTO);
}
Original file line number Diff line number Diff line change
Expand Up @@ -869,4 +869,68 @@ public Response<List<UserInfoVO>> operator() {
}
return Response.responseData(result);
}

@Override
public Response<String> resetPhoneNumber(ResetPhoneDTO resetPhoneDTO) {
var verifyCode = redisUtil.getString(SecurityConstants.UPDATE_PHONE_VERIFY_CODE_CACHE_PREFIX + resetPhoneDTO.getPhoneNumber());
if (ObjectUtils.isEmpty(verifyCode)) {
return Response.responseMsg(BaseCodeEnum.SMS_VERIFY_CODE_EXPIRE);
}

if (!verifyCode.equals(resetPhoneDTO.getSms())) {
return Response.responseMsg(BaseCodeEnum.SMS_VERIFY_CODE_ERROR);
}

var phoneExist = lambdaQuery()
.eq(SysUser::getId, resetPhoneDTO.getUserId())
.eq(SysUser::getPhoneNumber, resetPhoneDTO.getPhoneNumber())
.one();
if (phoneExist == null) {
if(checkPhoneNumberExist(resetPhoneDTO.getPhoneNumber())) {
return Response.responseMsg(UserCodeEnum.PHONE_EXISTS);
}
}

var updateResult = lambdaUpdate()
.eq(SysUser::getId, resetPhoneDTO.getUserId())
.set(SysUser::getPhoneNumber, resetPhoneDTO.getPhoneNumber())
.update();

if(updateResult) {
return Response.responseMsg(UserCodeEnum.USER_PHONE_UPDATE_SUCCESS);
}
return Response.responseMsg(UserCodeEnum.USER_PHONE_UPDATE_ERROR);
}

@Override
public Response<String> resetEmail(ResetEmailDTO resetEmailDTO) {
var verifyCode = redisUtil.getString(SecurityConstants.EMAIL_RESET_VERIFY_CODE_CACHE_PREFIX + resetEmailDTO.getEmail());
if (ObjectUtils.isEmpty(verifyCode)) {
return Response.responseMsg(BaseCodeEnum.EMAIL_VERIFY_CODE_EXPIRE);
}

if (!verifyCode.equals(resetEmailDTO.getEmailCode())) {
return Response.responseMsg(BaseCodeEnum.EMAIL_VERIFY_CODE_ERROR);
}

var emailExist = lambdaQuery()
.eq(SysUser::getId, resetEmailDTO.getUserId())
.eq(SysUser::getEmail, resetEmailDTO.getEmail())
.one();
if (emailExist == null) {
if(checkPhoneNumberExist(resetEmailDTO.getEmail())) {
return Response.responseMsg(UserCodeEnum.EMAIL_EXISTS);
}
}

var updateResult = lambdaUpdate()
.eq(SysUser::getId, resetEmailDTO.getUserId())
.set(SysUser::getEmail, resetEmailDTO.getEmail())
.update();

if(updateResult) {
return Response.responseMsg(UserCodeEnum.USER_EMAIL_UPDATE_SUCCESS);
}
return Response.responseMsg(UserCodeEnum.USER_EMAIL_UPDATE_ERROR);
}
}
4 changes: 2 additions & 2 deletions core/utils/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
<version>1.5.6</version>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.5.3</version>
<version>1.6.2</version>
</dependency>
<!--http-->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2023-2033 WanSen AI Team, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
* with the License. A copy of the License is located at
*
* http://opensource.wansenai.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
package com.wansenai.utils.constants;

public interface EmailConstant {

/** 邮箱域 */
String EMAIL_HOST = "smtp.163.com";

String EMAIL_USER_NAME = "wanstech@163.com";

/** 邮箱授权码 */
String EMAIL_PASSWORD = "YSWXSMYYQSVDSBYL";

/** 邮件HMAC256加密算法头字符串 */
String EMAIL_HMAC256_TOKEN_HEAD = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";

/** 邮件HMAC256加密算法ayload字符串 */
String EMAIL_HMAC256_TOKEN_PAYLOAD = "eyJsb2dpbkVtYWlsIjoiemhhb3dlaUBpaHVwLm9yZy5jbiIsImV4cCI6MTYwMDg0MDUyOSwidXNlcm5hbWUiOiJ6aGFvd2VpIn0";
}
Loading

0 comments on commit 89a7502

Please sign in to comment.