Browse Source

双Token功能实现

dev_ycq
21819 2 years ago
parent
commit
2b080363c7
  1. 5
      mailbox-outer-admin/pom.xml
  2. 9
      mailbox-outer-admin/src/main/java/com/biutag/outeradmin/config/LoginConfig.java
  3. 21
      mailbox-outer-admin/src/main/java/com/biutag/outeradmin/config/UserLoginInterceptor.java
  4. 2
      mailbox-outer-admin/src/main/java/com/biutag/outeradmin/controller/HolidayController.java
  5. 49
      mailbox-outer-admin/src/main/java/com/biutag/outeradmin/controller/JwtController.java
  6. 26
      mailbox-outer-admin/src/main/java/com/biutag/outeradmin/controller/LoginController.java
  7. 8
      mailbox-outer-admin/src/main/java/com/biutag/outeradmin/controller/MailController.java
  8. 7
      mailbox-outer-admin/src/main/java/com/biutag/outeradmin/controller/UserController.java
  9. 14
      mailbox-outer-admin/src/main/java/com/biutag/outeradmin/dto/TokenDTO.java
  10. 14
      mailbox-outer-admin/src/main/java/com/biutag/outeradmin/exception/GlobalExceptionHandler.java
  11. 14
      mailbox-outer-admin/src/main/java/com/biutag/outeradmin/exception/TokenException.java
  12. 68
      mailbox-outer-admin/src/main/java/com/biutag/outeradmin/interceptor/UserLoginInterceptor.java
  13. 107
      mailbox-outer-admin/src/main/java/com/biutag/outeradmin/util/JwtUtil.java
  14. 22
      mailbox-outer-admin/src/main/java/com/biutag/outeradmin/util/PhoneEncryptUtil.java

5
mailbox-outer-admin/pom.xml

@ -69,6 +69,11 @@
<artifactId>easyexcel</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.12.3</version>
</dependency>
</dependencies>

9
mailbox-outer-admin/src/main/java/com/biutag/outeradmin/config/LoginConfig.java

@ -1,5 +1,7 @@
package com.biutag.outeradmin.config;
import com.biutag.outeradmin.interceptor.UserLoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
@ -7,13 +9,16 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class LoginConfig implements WebMvcConfigurer {
@Autowired
private UserLoginInterceptor userLoginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration interceptorRegistration = registry.addInterceptor(new UserLoginInterceptor());
InterceptorRegistration interceptorRegistration = registry.addInterceptor(userLoginInterceptor);
interceptorRegistration.addPathPatterns("/**");
interceptorRegistration.excludePathPatterns(
"/login",
"/captcha"
"/captcha",
"/refresh-token"
);
}
}

21
mailbox-outer-admin/src/main/java/com/biutag/outeradmin/config/UserLoginInterceptor.java

@ -1,21 +0,0 @@
package com.biutag.outeradmin.config;
import com.biutag.outeradmin.entity.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.servlet.HandlerInterceptor;
public class UserLoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
if (user != null)
return true;
// response.sendRedirect(request.getContextPath() + "/login");
return false;
}
}

2
mailbox-outer-admin/src/main/java/com/biutag/outeradmin/controller/HolidayController.java

@ -39,14 +39,12 @@ public class HolidayController {
String currentYear = Integer.toString(currentDate.getYear());
// String currentYear = "2025";
if (getYear.getYear().equals(currentYear)) {
System.out.println("年份相同");
holidayRefresh.setMessage("success");
} else {
holidayMapper.delete(null);
List<Holiday> holidays = HolidayUtil.getAllHolidayByYear(getYear.getYear());
holidayService.saveBatch(holidays);
holidayRefresh.setMessage("success");
System.out.println("年份不同,重写数据库");
}
holidayRefresh.setHolidayList(getlist());
return holidayRefresh;

49
mailbox-outer-admin/src/main/java/com/biutag/outeradmin/controller/JwtController.java

@ -0,0 +1,49 @@
package com.biutag.outeradmin.controller;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.biutag.outeradmin.dto.TokenDTO;
import com.biutag.outeradmin.entity.User;
import com.biutag.outeradmin.service.UserService;
import com.biutag.outeradmin.util.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequiredArgsConstructor
public class JwtController {
private final UserService userService;
@RequestMapping("/refresh-token")
public TokenDTO refreshToken(@RequestBody String reToken) {
TokenDTO tokenDTOReceived = JSON.parseObject(reToken, TokenDTO.class);
String token = tokenDTOReceived.getRefreshToken();
log.info("refresh_token:{}", token);
try {
Claims claims = JwtUtil.parseJwtToken(token).getPayload();
log.info("refresh token:{}", token);
log.info("claims:{}", claims);
String phone = claims.get("username", String.class);
TokenDTO tokenDTO = new TokenDTO();
User user = userService.getOne(new QueryWrapper<User>().eq("phone", phone));
// 如果用户存在,就生成一个新的令牌
if (user != null) {
String refreshToken = JwtUtil.getNewRefreshToken(token);
String accessToken = JwtUtil.getNewAccessToken(token);
tokenDTO.setRefreshToken(refreshToken);
tokenDTO.setAccessToken(accessToken);
}
log.info("refresh token success:{}", tokenDTO.toString());
return tokenDTO;
} catch (Exception e) {
throw new RuntimeException();
}
}
}

26
mailbox-outer-admin/src/main/java/com/biutag/outeradmin/controller/LoginController.java

@ -4,17 +4,21 @@ import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.biutag.enums.ErrorEnum;
import com.biutag.outeradmin.dto.LoginFormData;
import com.biutag.outeradmin.dto.TokenDTO;
import com.biutag.outeradmin.entity.User;
import com.biutag.outeradmin.mapper.UserMapper;
import com.biutag.outeradmin.service.UserService;
import com.biutag.outeradmin.util.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor
@RestController
@Slf4j
public class LoginController {
private final UserService userService;
private final UserMapper userMapper;
@ -23,21 +27,25 @@ public class LoginController {
@RequestMapping("/login")
public int login(@RequestBody String formData, HttpServletRequest request) {
public TokenDTO login(@RequestBody String formData, HttpServletRequest request) {
LoginFormData data = JSON.parseObject(formData, LoginFormData.class);
System.out.println(data.toString());
System.out.println(randomCaptcha);
TokenDTO tokens = new TokenDTO();
if (!data.getCaptcha().equals(randomCaptcha)) {
return ErrorEnum.CAPTCHA_ERROR.getCode();
tokens.setStateCode(ErrorEnum.CAPTCHA_ERROR.getCode());
return tokens;
} else {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("phone", data.getAccount());
User user = userService.getOne(queryWrapper, false);
if (user == null) {
return ErrorEnum.LOGIN_ACCOUNT_ERROR.getCode();
tokens.setStateCode(ErrorEnum.LOGIN_ACCOUNT_ERROR.getCode());
return tokens;
} else {
request.getSession().setAttribute("user", user);
return ErrorEnum.SUCCESS.getCode();
tokens.setAccessToken(JwtUtil.buildJwtToken(data.getAccount(), data.getCaptcha(), false));
tokens.setRefreshToken(JwtUtil.buildJwtToken(data.getAccount(), data.getCaptcha(), true));
log.info("refresh_token:{}", tokens.getRefreshToken());
tokens.setStateCode(ErrorEnum.SUCCESS.getCode());
return tokens;
}
}
}
@ -59,8 +67,8 @@ public class LoginController {
}
@RequestMapping("/logout")
public int logout(HttpServletRequest request) {
request.getSession().removeAttribute("user");
public int logout() {
log.info("用户已登出");
return ErrorEnum.SUCCESS.getCode();
}
}

8
mailbox-outer-admin/src/main/java/com/biutag/outeradmin/controller/MailController.java

@ -50,14 +50,11 @@ public class MailController {
*/
@RequestMapping("/list-submit")
public MailPageInfo siftList(@RequestBody String form) {
//todo 这里根据表单数据查询数据库,记得删掉
System.out.println(form);
MailFormPage mailFormPage = JSON.parseObject(form, MailFormPage.class);
QueryWrapper<Mail> queryWrapper = new QueryWrapper<>();
if (mailFormPage != null && mailFormPage.getFormData() != null && mailFormPage.getPageData() != null) {
MailFormData mailFormData = mailFormPage.getFormData();
if (StringUtils.isNotEmpty(mailFormData.getEvaluate())) {
System.out.println(mailFormData.getEvaluate());
switch (mailFormData.getEvaluate()) {
case "不满意":
mailFormData.setEvaluate("NOT_SATISFIED");
@ -120,7 +117,6 @@ public class MailController {
public String detail(@RequestBody String id) {
MailID mailID = JSON.parseObject(id, MailID.class);
//TODO 这里根据ID查询数据库,记得删掉
System.out.println(mailID.getID());
Mail mail = mailService.getById(mailID.getID());
mail.setContactIdCard(DesensitizedUtil.encryptIDCard(mail.getContactIdCard()));
mail.setContactPhone(DesensitizedUtil.encryptPhone(mail.getContactPhone()));
@ -131,7 +127,7 @@ public class MailController {
public void exportexcel(HttpServletResponse response, @RequestBody String form) throws IOException {
MailFormPage formPage = JSON.parseObject(form, MailFormPage.class);
QueryWrapper<Mail> queryWrapper = new QueryWrapper<>();
if(formPage != null && formPage.getFormData()!= null && formPage.getPageData()!= null){
if (formPage != null && formPage.getFormData() != null && formPage.getPageData() != null) {
MailFormData formData = formPage.getFormData();
queryWrapper.lambda().like(StringUtils.isNotEmpty(formData.getContactName()), Mail::getContactName, formData.getContactName())
.like(StringUtils.isNotEmpty(formData.getContactPhone()), Mail::getContactPhone, formData.getContactPhone())
@ -143,7 +139,7 @@ public class MailController {
}
}
List<Mail> mailPage = mailMapper.selectList( queryWrapper);
List<Mail> mailPage = mailMapper.selectList(queryWrapper);
for (Mail mail : mailPage) {
mail.setContactIdCard(DesensitizedUtil.encryptIDCard(mail.getContactIdCard()));
mail.setContactPhone(DesensitizedUtil.encryptPhone(mail.getContactPhone()));

7
mailbox-outer-admin/src/main/java/com/biutag/outeradmin/controller/UserController.java

@ -33,10 +33,7 @@ public class UserController {
@RequestMapping("/list-submit")
public UserPageInfo siftList(@RequestBody String form) {
//todo 这里根据表单数据查询数据库,记得删掉
System.out.println(form);
UserFormPage userFormPage = JSON.parseObject(form, UserFormPage.class);
System.out.println(userFormPage);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
if (userFormPage != null && userFormPage.getFormData() != null && userFormPage.getPageData() != null) {
UserFormData formData = userFormPage.getFormData();
@ -67,7 +64,6 @@ public class UserController {
@RequestMapping("/add-user")
public String addUser(@RequestBody String form) {
UserFormData userForm = JSON.parseObject(form, UserFormData.class);
System.out.println("新用户数据" + userForm);
User user = new User();
user.setRealName(userForm.getRealName());
user.setPhone(userForm.getPhone());
@ -85,9 +81,8 @@ public class UserController {
}
@RequestMapping("/delete-user")
public String deleteUser(@RequestBody String id){
public String deleteUser(@RequestBody String id) {
User user = JSON.parseObject(id, User.class);
System.out.println("User数据为" + user);
userMapper.deleteById(user.getId());
return "success";
}

14
mailbox-outer-admin/src/main/java/com/biutag/outeradmin/dto/TokenDTO.java

@ -0,0 +1,14 @@
package com.biutag.outeradmin.dto;
import lombok.Data;
import org.apache.poi.ss.formula.functions.T;
import java.util.List;
@Data
public class TokenDTO {
private String accessToken;
private String refreshToken;
private int stateCode;
private List<T> list;
}

14
mailbox-outer-admin/src/main/java/com/biutag/outeradmin/exception/GlobalExceptionHandler.java

@ -0,0 +1,14 @@
package com.biutag.outeradmin.exception;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(TokenException.class)
public String handleTokenException(TokenException e, HttpServletResponse response) {
response.setStatus(e.getCode());
return e.getMessage();
}
}

14
mailbox-outer-admin/src/main/java/com/biutag/outeradmin/exception/TokenException.java

@ -0,0 +1,14 @@
package com.biutag.outeradmin.exception;
public class TokenException extends RuntimeException{
private int code;
public TokenException(int code, String message) {
super(message);
this.code = code;
}
public int getCode() {
return code;
}
}

68
mailbox-outer-admin/src/main/java/com/biutag/outeradmin/interceptor/UserLoginInterceptor.java

@ -0,0 +1,68 @@
package com.biutag.outeradmin.interceptor;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.biutag.outeradmin.entity.User;
import com.biutag.outeradmin.service.UserService;
import com.biutag.outeradmin.util.JwtUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.Date;
@Slf4j
@Component
public class UserLoginInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
try {
Claims claims = JwtUtil.parseJwtToken(token).getPayload();
String name = claims.get("username", String.class);
Date date = claims.getExpiration();
if (name != null && date != null && date.after(new Date())) {
log.info("用户{}已登录", name);
return true;
}
} catch (Exception e) {
if (e instanceof ExpiredJwtException) {
response.setStatus(401);
log.info("用户未登录或长时间未操作导致登陆失效");
return false;
}
throw new RuntimeException("Token无效或过期");
}
}
return false;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
if (ex == null) {
String token = request.getHeader("Authorization");
token = token.substring(7);
Claims claims = JwtUtil.parseJwtToken(token).getPayload();
String phone = claims.get("username", String.class);
User user = userService.getOne(new QueryWrapper<User>().eq("phone", phone));
// 如果用户存在,就生成一个新的令牌
if (user != null) {
String newToken = JwtUtil.getNewAccessToken(token);
// 将新的令牌添加到响应头中
response.setHeader("Authorization", "Bearer " + newToken);
log.info("用户{}的令牌已更新", phone);
}
}
}
}

107
mailbox-outer-admin/src/main/java/com/biutag/outeradmin/util/JwtUtil.java

@ -0,0 +1,107 @@
package com.biutag.outeradmin.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwsHeader;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SecureDigestAlgorithm;
import lombok.extern.slf4j.Slf4j;
import javax.crypto.SecretKey;
import java.time.Instant;
import java.util.Date;
@Slf4j
public class JwtUtil {
// TODO 正式上线以后需要修改accessToken持续时间
public static final long EXPIRATION_TIME = 5; // 1h
public static final long REFRESH_TIME = 60 * 60 * 24 * 7;
public static final String APP_SECRET = "5FtX1OpGWKBVyaIh3dwRl04gkAzLro6U";
public static final SecretKey KEY = Keys.hmacShaKeyFor(APP_SECRET.getBytes());
public static final SecureDigestAlgorithm<SecretKey, SecretKey> ALGORITHM = Jwts.SIG.HS256;
private final static String JWT_ISS = "admin";
private final static String SUBJECT = "Peripherals";
/**
* 构建双Token
*
* @param phone 用户手机号
* @param captcha 验证码
* @param ifRefresh 是否refreshToken控制参数
* @return
*/
public static String buildJwtToken(String phone, String captcha, boolean ifRefresh) {
Date exprireDate = Date.from(Instant.now().plusSeconds(EXPIRATION_TIME));
if (ifRefresh)
exprireDate = Date.from(Instant.now().plusSeconds(REFRESH_TIME));
return Jwts.builder()
.header().add("typ", "JWT").add("alg", "HS256")
.and()
.claim("username", phone).id(captcha)
.expiration(exprireDate)
.issuedAt(new Date())
.subject(SUBJECT)
.issuer(JWT_ISS)
.signWith(KEY, ALGORITHM)
.compact();
}
/**
* 在accessToken发送过来时刷新refreshToken
*
* @param Token
* @return
*/
public static String getNewRefreshToken(String Token) {
Jws<Claims> data = parseJwtToken(Token);
String name = data.getPayload().get("username", String.class);
String captcha = data.getPayload().getId();
return buildJwtToken(name, captcha, true);
}
/**
* accessToken过期时依据未过期的refreshToken刷新accessToken
*
* @param refreshToken
* @return
*/
public static String getNewAccessToken(String refreshToken) {
Jws<Claims> data = parseJwtToken(refreshToken);
String name = data.getPayload().get("username", String.class);
String captcha = data.getPayload().getId();
return buildJwtToken(name, captcha, true);
}
/**
* 解析Token
*
* @param token
* @return
*/
public static Jws<Claims> parseJwtToken(String token) {
return Jwts.parser().verifyWith(KEY).build().parseSignedClaims(token);
}
/**
* 解析Token中的header
*
* @param token
* @return
*/
public static JwsHeader parseTokenHeader(String token) {
return parseJwtToken(token).getHeader();
}
/**
* 解析Token中的payload
*
* @param token
* @return
*/
public static Claims parsePayload(String token) {
return parseJwtToken(token).getPayload();
}
}

22
mailbox-outer-admin/src/main/java/com/biutag/outeradmin/util/PhoneEncryptUtil.java

@ -0,0 +1,22 @@
package com.biutag.outeradmin.util;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
public class PhoneEncryptUtil {
private static final String KEY = "D9ioYl2WCeVRfLXvg4FrqZ51UtT8Ewcz";
private static AES init() {
String result = "";
byte[] key = SecureUtil.generateKey(KEY).getEncoded();
return new AES(key);
}
public static String encrypt(String phone) {
return init().encryptHex(phone);
}
public static String decrypt(String phone) {
return init().decryptStr(phone);
}
}
Loading…
Cancel
Save