Merge pull request 'dev' (#5) from dev into master
Reviewed-on: #5 JWT错误异常处理,AOP切面日志
This commit is contained in:
commit
ed87f568c5
|
@ -1,27 +0,0 @@
|
|||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>common-utils</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>common-utils</name>
|
||||
<url>https://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>dao</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -14,7 +14,6 @@
|
|||
<modules>
|
||||
<module>service-utils</module>
|
||||
<module>common-generator</module>
|
||||
<module>common-utils</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
|
|
@ -22,6 +22,12 @@
|
|||
<artifactId>dao</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!-- 解决 javax.xml.bind 错误 -->
|
||||
<dependency>
|
||||
<groupId>javax.xml.bind</groupId>
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
<version>2.3.1</version>
|
||||
</dependency>
|
||||
<!-- httpclient -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
|
|
|
@ -2,10 +2,10 @@ package cn.bunny.common.service.interceptor;
|
|||
|
||||
import cn.bunny.common.service.context.BaseContext;
|
||||
import cn.bunny.common.service.utils.JwtHelper;
|
||||
import cn.bunny.common.service.utils.ResponseUtil;
|
||||
import cn.bunny.pojo.result.Result;
|
||||
import cn.bunny.pojo.result.ResultCodeEnum;
|
||||
import cn.bunny.pojo.result.constant.RedisUserConstant;
|
||||
import cn.bunny.vo.system.login.LoginVo;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -16,34 +16,53 @@ import org.springframework.stereotype.Component;
|
|||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.bunny.common.service.utils.ResponseHandlerUtil.loginAuthHandler;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class UserTokenInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
log.info("UserTokenInterceptor===>设置拦截器");
|
||||
// 获取token
|
||||
String token = request.getHeader("token");
|
||||
Long userId = JwtHelper.getUserId(token);
|
||||
String username = JwtHelper.getUsername(token);
|
||||
Object redisUserinfo = redisTemplate.opsForValue().get(RedisUserConstant.getUserLoginInfoPrefix(username));
|
||||
|
||||
// token为空时
|
||||
if (token == null) {
|
||||
return loginAuthHandler(response, ResultCodeEnum.LOGIN_AUTH);
|
||||
}
|
||||
|
||||
// 当token过期
|
||||
if (JwtHelper.isExpired(token)) {
|
||||
return loginAuthHandler(response, ResultCodeEnum.AUTHENTICATION_EXPIRED);
|
||||
}
|
||||
|
||||
// 将token转成实体类
|
||||
Map<String, Object> tokenByMap = JwtHelper.getMapByToken(token);
|
||||
LoginVo loginVo = JSONObject.parseObject(JSONObject.toJSONString(tokenByMap), LoginVo.class);
|
||||
|
||||
// 获取用户id和用户邮箱
|
||||
Long userId = loginVo.getId();
|
||||
String email = loginVo.getEmail();
|
||||
String redisKey = RedisUserConstant.getUserLoginInfoPrefix(email);
|
||||
Object redisUserinfo = redisTemplate.opsForValue().get(redisKey);
|
||||
|
||||
// 不是动态方法直接返回
|
||||
if (!(handler instanceof HandlerMethod)) return true;
|
||||
// 解析不到userId
|
||||
if (userId == null) {
|
||||
ResponseUtil.out(response, Result.error(ResultCodeEnum.LOGIN_AUTH));
|
||||
return false;
|
||||
}
|
||||
if (redisUserinfo == null) {
|
||||
ResponseUtil.out(response, Result.error(ResultCodeEnum.LOGIN_AUTH));
|
||||
return false;
|
||||
|
||||
// 解析不到userId,Redis中没有这个用户
|
||||
if (userId == null || redisUserinfo == null) {
|
||||
return loginAuthHandler(response, ResultCodeEnum.LOGIN_AUTH);
|
||||
}
|
||||
|
||||
BaseContext.setUserId(userId);
|
||||
BaseContext.setUsername(username);
|
||||
BaseContext.setUsername(email);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package cn.bunny.common.utils;
|
||||
package cn.bunny.common.service.utils;
|
||||
|
||||
/**
|
||||
* 计算 kb mb gb
|
|
@ -1,50 +1,350 @@
|
|||
package cn.bunny.common.service.utils;
|
||||
|
||||
import io.jsonwebtoken.*;
|
||||
import io.micrometer.common.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class JwtHelper {
|
||||
// 时间 按天 计算
|
||||
private static final long tokenExpiration = 24 * 60 * 60 * 1000;
|
||||
// JWT 的 秘钥
|
||||
private static final String tokenSignKey = "Bunny-Java-Template";
|
||||
// 默认主题
|
||||
private static final String subject = "Bunny";
|
||||
// 默认时间
|
||||
private static final Date time = new Date(System.currentTimeMillis() + tokenExpiration * 7);
|
||||
|
||||
public static String createToken(Long userId, String userName, Integer day) {
|
||||
/**
|
||||
* 使用默认主题,默认时间,默认秘钥,创建自定义集合token
|
||||
*
|
||||
* @param map 集合
|
||||
* @return token
|
||||
*/
|
||||
public static String createTokenWithMap(Map<String, Object> map) {
|
||||
return Jwts.builder()
|
||||
.setSubject("Bunny-USER")
|
||||
.setSubject(subject)
|
||||
.setExpiration(time)
|
||||
.signWith(SignatureAlgorithm.HS256, tokenSignKey)
|
||||
.setClaims(map)
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.compressWith(CompressionCodecs.GZIP).compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用默认主题,默认秘钥,自定义时间,创建集合形式token
|
||||
*
|
||||
* @param map 集合
|
||||
* @param time 过期时间
|
||||
* @return token
|
||||
*/
|
||||
public static String createTokenWithMap(Map<String, Object> map, Date time) {
|
||||
return Jwts.builder()
|
||||
.setSubject(subject)
|
||||
.signWith(SignatureAlgorithm.HS256, tokenSignKey)
|
||||
.setExpiration(time)
|
||||
.setClaims(map)
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.compressWith(CompressionCodecs.GZIP).compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用默认主题,默认秘钥,自定义时间,创建集合形式token
|
||||
*
|
||||
* @param map 集合
|
||||
* @param day 过期时间
|
||||
* @return token
|
||||
*/
|
||||
public static String createTokenWithMap(Map<String, Object> map, Integer day) {
|
||||
return Jwts.builder()
|
||||
.setSubject(subject)
|
||||
.signWith(SignatureAlgorithm.HS256, tokenSignKey)
|
||||
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * day))
|
||||
.claim("userId", userId)
|
||||
.claim("userName", userName)
|
||||
.setClaims(map)
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.compressWith(CompressionCodecs.GZIP).compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用默认主题,默认秘钥,自定义key,创建集合形式token
|
||||
*
|
||||
* @param map 集合
|
||||
* @param tokenSignKey 自定义key
|
||||
* @return token
|
||||
*/
|
||||
public static String createTokenWithMap(Map<String, Object> map, String tokenSignKey) {
|
||||
return Jwts.builder()
|
||||
.setSubject(subject)
|
||||
.setExpiration(time)
|
||||
.signWith(SignatureAlgorithm.HS256, tokenSignKey)
|
||||
.setClaims(map)
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.compressWith(CompressionCodecs.GZIP).compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用自定义主题,自定义时间,创建集合形式token
|
||||
*
|
||||
* @param map 集合
|
||||
* @param subject 主题
|
||||
* @param time 过期时间
|
||||
* @return token
|
||||
*/
|
||||
public static String createTokenWithMap(Map<String, Object> map, String subject, Date time) {
|
||||
return Jwts.builder()
|
||||
.setSubject(subject)
|
||||
.setExpiration(time)
|
||||
.setClaims(map)
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.signWith(SignatureAlgorithm.HS256, tokenSignKey)
|
||||
.compressWith(CompressionCodecs.GZIP)
|
||||
.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建集合形式token
|
||||
*
|
||||
* @param map 集合
|
||||
* @param subject 主题
|
||||
* @param tokenSignKey 过期时间
|
||||
* @return token
|
||||
*/
|
||||
public static String createTokenWithMap(Map<String, Object> map, String subject, String tokenSignKey) {
|
||||
return Jwts.builder()
|
||||
.setSubject(subject)
|
||||
.setExpiration(time)
|
||||
.signWith(SignatureAlgorithm.HS256, tokenSignKey)
|
||||
.setClaims(map)
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.compressWith(CompressionCodecs.GZIP).compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建集合形式token
|
||||
*
|
||||
* @param map 集合
|
||||
* @param tokenSignKey 主题
|
||||
* @param time 过期时间
|
||||
* @return token
|
||||
*/
|
||||
public static String createTokenWithMap(Map<String, Object> map, String tokenSignKey, Integer time) {
|
||||
return Jwts.builder()
|
||||
.setSubject(subject)
|
||||
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * time))
|
||||
.setClaims(map)
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.signWith(SignatureAlgorithm.HS256, tokenSignKey)
|
||||
.compressWith(CompressionCodecs.GZIP)
|
||||
.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建集合形式token
|
||||
*
|
||||
* @param map 集合
|
||||
* @param subject 主题
|
||||
* @param day 过期时间
|
||||
* @return token
|
||||
*/
|
||||
public static String createTokenWithMap(Map<String, Object> map, String subject, String tokenSignKey, Integer day) {
|
||||
return Jwts.builder()
|
||||
.setSubject(subject)
|
||||
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * day))
|
||||
.setClaims(map)
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.signWith(SignatureAlgorithm.HS256, tokenSignKey)
|
||||
.compressWith(CompressionCodecs.GZIP)
|
||||
.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建集合形式token
|
||||
*
|
||||
* @param map 集合
|
||||
* @param subject 主题
|
||||
* @param time 过期时间
|
||||
* @return token
|
||||
*/
|
||||
public static String createTokenWithMap(Map<String, Object> map, String subject, String tokenSignKey, Date time) {
|
||||
return Jwts.builder()
|
||||
.setSubject(subject)
|
||||
.setExpiration(time)
|
||||
.setClaims(map)
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.signWith(SignatureAlgorithm.HS256, tokenSignKey)
|
||||
.compressWith(CompressionCodecs.GZIP)
|
||||
.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户名和ID创建token
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param userName 用户名
|
||||
* @param day 过期时间
|
||||
* @return token值
|
||||
*/
|
||||
public static String createToken(Long userId, String userName, Integer day) {
|
||||
return Jwts.builder()
|
||||
.setSubject(subject)
|
||||
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * day))
|
||||
.claim("userId", userId)
|
||||
.claim("userName", userName)
|
||||
.setId(UUID.randomUUID().toString())
|
||||
.signWith(SignatureAlgorithm.HS256, tokenSignKey)
|
||||
.compressWith(CompressionCodecs.GZIP)
|
||||
.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用token获取map集合,使用默认秘钥
|
||||
*
|
||||
* @param token token
|
||||
* @return map集合
|
||||
*/
|
||||
public static Map<String, Object> getMapByToken(String token) {
|
||||
try {
|
||||
if (!StringUtils.hasText(token)) return null;
|
||||
Claims claims = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody();
|
||||
|
||||
// 将 body 值转为map
|
||||
return new HashMap<>(claims);
|
||||
|
||||
} catch (Exception exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用token获取map集合
|
||||
*
|
||||
* @param token token
|
||||
* @param signKey 秘钥
|
||||
* @return map集合
|
||||
*/
|
||||
public static Map<String, Object> getMapByToken(String token, String signKey) {
|
||||
try {
|
||||
if (!StringUtils.hasText(token)) return null;
|
||||
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(signKey).parseClaimsJws(token);
|
||||
Claims body = claimsJws.getBody();
|
||||
// 将 body 值转为map
|
||||
return new HashMap<>(body);
|
||||
|
||||
} catch (Exception exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据token获取主题
|
||||
*
|
||||
* @param token token
|
||||
* @return 主题
|
||||
*/
|
||||
public static String getSubjectByToken(String token) {
|
||||
return getSubjectByTokenHandler(token, tokenSignKey);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getSubjectByTokenHandler(String token, String tokenSignKey) {
|
||||
try {
|
||||
if (!StringUtils.hasText(token)) return null;
|
||||
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
|
||||
Claims body = claimsJws.getBody();
|
||||
|
||||
return body.getSubject();
|
||||
|
||||
} catch (Exception exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据token获取主题
|
||||
*
|
||||
* @param token token
|
||||
* @return 主题
|
||||
*/
|
||||
public static String getSubjectByToken(String token, String tokenSignKey) {
|
||||
return getSubjectByTokenHandler(token, tokenSignKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据token获取用户ID
|
||||
*
|
||||
* @param token token
|
||||
* @return 用户ID
|
||||
*/
|
||||
public static Long getUserId(String token) {
|
||||
if (!StringUtils.hasText(token)) return null;
|
||||
try {
|
||||
if (!StringUtils.hasText(token)) return null;
|
||||
|
||||
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
|
||||
Claims claims = claimsJws.getBody();
|
||||
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
|
||||
Claims claims = claimsJws.getBody();
|
||||
|
||||
return Long.valueOf(String.valueOf(claims.get("userId")));
|
||||
return Long.valueOf(String.valueOf(claims.get("userId")));
|
||||
} catch (Exception exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据token获取用户名
|
||||
*
|
||||
* @param token token
|
||||
* @return 用户名
|
||||
*/
|
||||
public static String getUsername(String token) {
|
||||
if (!StringUtils.hasText(token)) return "";
|
||||
try {
|
||||
if (!StringUtils.hasText(token)) return "";
|
||||
|
||||
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
|
||||
Claims claims = claimsJws.getBody();
|
||||
return (String) claims.get("userName");
|
||||
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
|
||||
Claims claims = claimsJws.getBody();
|
||||
return (String) claims.get("userName");
|
||||
} catch (Exception exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeToken(String token) {
|
||||
// jwttoken无需删除,客户端扔掉即可。
|
||||
/**
|
||||
* 判断token是否过期
|
||||
*
|
||||
* @param token token
|
||||
* @return 是否过期
|
||||
*/
|
||||
public static boolean isExpired(String token) {
|
||||
return isExpiredUtil(token, tokenSignKey);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String token = JwtHelper.createToken(7L, "admin", 7);
|
||||
// token = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_6tWKi5NUrJScirNy6vUDQ12DVLSUUqtKFCyMjQ3MTc0NrYwNddRKi1OLfJMUbKyNDIwNLQwMDAzg4j5JeamAjUbGhtaWhoYGJqaOBQW6iXn5yrVAgCrO9jLWAAAAA.DS1wYprXGoIMrjtUWfDSN9AG5gWoRZ17oAgcvC0kwag";
|
||||
System.out.println(JwtHelper.getUserId(token));
|
||||
System.out.println(JwtHelper.getUsername(token));
|
||||
/**
|
||||
* 判断token是否过期
|
||||
*
|
||||
* @param token token
|
||||
* @return 是否过期
|
||||
*/
|
||||
public static boolean isExpired(String token, String tokenSignKey) {
|
||||
return isExpiredUtil(token, tokenSignKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否过期
|
||||
*
|
||||
* @param token token
|
||||
* @param tokenSignKey key值
|
||||
* @return 是否过期
|
||||
*/
|
||||
private static boolean isExpiredUtil(String token, String tokenSignKey) {
|
||||
try {
|
||||
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
|
||||
Date expiration = claimsJws.getBody().getExpiration();
|
||||
|
||||
return expiration != null && expiration.before(new Date());
|
||||
} catch (Exception exception) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package cn.bunny.common.service.utils;
|
||||
|
||||
import cn.bunny.pojo.result.Result;
|
||||
import cn.bunny.pojo.result.ResultCodeEnum;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
public class ResponseHandlerUtil {
|
||||
public static boolean loginAuthHandler(HttpServletResponse response, ResultCodeEnum loginAuth) {
|
||||
ResponseUtil.out(response, Result.error(loginAuth));
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package cn.bunny.entity.system.log;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 系统日志表
|
||||
* </p>
|
||||
*
|
||||
* @author Bunny
|
||||
* @since 2024-05-31
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Accessors(chain = true)
|
||||
@TableName("system_log")
|
||||
@ApiModel(value = "SystemLog对象", description = "系统日志表")
|
||||
public class SystemLog implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("所在类路径")
|
||||
private String classPath;
|
||||
|
||||
@ApiModelProperty("执行方法名称")
|
||||
private String methodName;
|
||||
|
||||
@ApiModelProperty("入参内容")
|
||||
private Object args;
|
||||
|
||||
@ApiModelProperty("返回参数")
|
||||
private String result;
|
||||
|
||||
@ApiModelProperty("报错堆栈")
|
||||
private String errorStack;
|
||||
|
||||
@ApiModelProperty("报错")
|
||||
private String errorMessage;
|
||||
|
||||
@ApiModelProperty("邮箱")
|
||||
private String email;
|
||||
|
||||
@ApiModelProperty("用户名")
|
||||
private String nickname;
|
||||
|
||||
@ApiModelProperty("当前用户token")
|
||||
private String token;
|
||||
|
||||
@ApiModelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@ApiModelProperty("更新时间")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@ApiModelProperty("更新用户")
|
||||
private Long updateUser;
|
||||
|
||||
@ApiModelProperty("是否被删除")
|
||||
private Boolean isDeleted;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package cn.bunny.service.aop.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SkipLog {
|
||||
}
|
|
@ -11,7 +11,7 @@ import org.springframework.stereotype.Component;
|
|||
@Component
|
||||
@Slf4j
|
||||
public class AutoFillAspect {
|
||||
@Pointcut("execution(* cn.bunny.service.*.*(..))")
|
||||
@Pointcut("execution(* cn.bunny.service.web.service.impl..*(..))")
|
||||
public void autoFillPointcut() {
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
package cn.bunny.service.aop.aspect;
|
||||
|
||||
import cn.bunny.common.service.utils.JwtHelper;
|
||||
import cn.bunny.entity.system.log.SystemLog;
|
||||
import cn.bunny.service.aop.annotation.SkipLog;
|
||||
import cn.bunny.service.mapper.SystemLogMapper;
|
||||
import cn.bunny.vo.system.login.LoginVo;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
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.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AutoLogAspect {
|
||||
@Autowired
|
||||
private SystemLogMapper systemLogMapper;
|
||||
|
||||
@Pointcut("execution(* cn.bunny.service.web.controller..*(..))")
|
||||
public void point() {
|
||||
}
|
||||
|
||||
@Around(value = "point()")
|
||||
public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
Object result;
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
// 是否有跳过注解,如果有跳过注解就不执行当前操作!!!
|
||||
SkipLog annotation = signature.getMethod().getAnnotation(SkipLog.class);
|
||||
// 目标方法所在类名路径
|
||||
String classPath = joinPoint.getSignature().getDeclaringTypeName();
|
||||
// 当前执行的方法名
|
||||
String methodName = signature.getName();
|
||||
// 入参内容
|
||||
String args = Arrays.toString(joinPoint.getArgs());
|
||||
// 获取用户token
|
||||
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = requestAttributes.getRequest();
|
||||
String token = request.getHeader("token");
|
||||
// 初始化系统日志对象
|
||||
SystemLog systemLog = new SystemLog();
|
||||
// token转为实体对象
|
||||
Map<String, Object> mapByToken = JwtHelper.getMapByToken(token);
|
||||
LoginVo loginVo = JSONObject.parseObject(JSONObject.toJSONString(mapByToken), LoginVo.class);
|
||||
|
||||
|
||||
try {
|
||||
// 当为null时跳过执行
|
||||
if (annotation != null) return joinPoint.proceed();
|
||||
|
||||
// TODO 将请求头token全部转成 map
|
||||
systemLog.setClassPath(classPath);
|
||||
systemLog.setMethodName(methodName);
|
||||
if (args.equals("[null]")) {
|
||||
systemLog.setArgs(null);
|
||||
} else {
|
||||
systemLog.setArgs(args);
|
||||
}
|
||||
systemLog.setToken(token);
|
||||
|
||||
systemLog.setNickname(loginVo.getNickName());
|
||||
systemLog.setEmail(loginVo.getEmail());
|
||||
systemLog.setUpdateUser(loginVo.getId());
|
||||
|
||||
// 目标对象(连接点)方法的执行
|
||||
result = joinPoint.proceed();
|
||||
systemLog.setResult(JSONObject.toJSONString(result));
|
||||
} catch (Exception exception) {
|
||||
String message = exception.getMessage();
|
||||
StackTraceElement[] stackTrace = exception.getStackTrace();
|
||||
|
||||
// 如果报错,设置报错的堆栈和消息,放到数据库中
|
||||
systemLog.setErrorStack(Arrays.toString(stackTrace));
|
||||
systemLog.setErrorMessage(message);
|
||||
|
||||
// 插入日志数据到数据库
|
||||
systemLogMapper.insert(systemLog);
|
||||
|
||||
throw exception;
|
||||
}
|
||||
|
||||
// 插入日志数据到数据库
|
||||
systemLogMapper.insert(systemLog);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -13,6 +13,6 @@ public class IndexController {
|
|||
@Operation(summary = "访问首页", description = "访问首页")
|
||||
@GetMapping("")
|
||||
public String index() {
|
||||
return "欢迎访问 Bunny Java Template";
|
||||
return "欢迎访问 Bunny Java Template,欢迎去Gitee:https://gitee.com/BunnyBoss/java_single.git";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package cn.bunny.service.mapper;
|
||||
|
||||
import cn.bunny.entity.system.log.SystemLog;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 系统日志表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author Bunny
|
||||
* @since 2024-05-31
|
||||
*/
|
||||
@Mapper
|
||||
public interface SystemLogMapper extends BaseMapper<SystemLog> {
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.bunny.service.mapper.SystemLogMapper">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="cn.bunny.entity.system.log.SystemLog">
|
||||
<id column="id" property="id"/>
|
||||
<result column="class_path" property="classPath"/>
|
||||
<result column="method_name" property="methodName"/>
|
||||
<result column="args" property="args"/>
|
||||
<result column="result" property="result"/>
|
||||
<result column="error_stack" property="errorStack"/>
|
||||
<result column="error_message" property="errorMessage"/>
|
||||
<result column="email" property="email"/>
|
||||
<result column="nickname" property="nickname"/>
|
||||
<result column="token" property="token"/>
|
||||
<result column="create_time" property="createTime"/>
|
||||
<result column="update_time" property="updateTime"/>
|
||||
<result column="update_user" property="updateUser"/>
|
||||
<result column="is_deleted" property="isDeleted"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
id, class_path, method_name, args, result, error_stack, error_message, email, nickname, token, create_time, update_time, update_user, is_deleted
|
||||
</sql>
|
||||
|
||||
</mapper>
|
|
@ -0,0 +1,122 @@
|
|||
package cn.bunny.jwt;
|
||||
|
||||
import cn.bunny.common.service.utils.JwtHelper;
|
||||
import cn.bunny.entity.system.user.User;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
class JwtHelperTest {
|
||||
private static final String key = "my-key";
|
||||
private static final String subject = "my-subject";
|
||||
|
||||
private static Map getMap() {
|
||||
User user = new User();
|
||||
user.setId(123L);
|
||||
user.setAvatar("http://129.211.31.58:4000/#/chat");
|
||||
user.setEmail("user@example.com");
|
||||
user.setNickName("user@example.com");
|
||||
|
||||
// 将对象转为map
|
||||
Map map = JSONObject.parseObject(JSONArray.toJSONString(user), Map.class);
|
||||
return map;
|
||||
}
|
||||
|
||||
@Test
|
||||
void createTokenWithMap() {
|
||||
// 自定义 天数过期
|
||||
String token = JwtHelper.createTokenWithMap(getMap());
|
||||
System.out.println(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateTokenWithMap() {
|
||||
// 自定义key
|
||||
String token = JwtHelper.createTokenWithMap(getMap(), new Date(System.currentTimeMillis() + 666666));
|
||||
System.out.println(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createTokenWithMap0() {
|
||||
// 自定义 天数过期
|
||||
String token = JwtHelper.createTokenWithMap(getMap(), 1);
|
||||
System.out.println(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateTokenWithMap1() {
|
||||
// 自定义 天数过期
|
||||
String token = JwtHelper.createTokenWithMap(getMap(), key);
|
||||
System.out.println(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateTokenWithMap2() {
|
||||
// 自定义 天数过期
|
||||
String token = JwtHelper.createTokenWithMap(getMap(), subject, key);
|
||||
System.out.println(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateTokenWithMap3() {
|
||||
// 自定义 天数过期
|
||||
String token = JwtHelper.createTokenWithMap(getMap(), subject, 7);
|
||||
System.out.println(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createToken1() {
|
||||
// 自定义 天数过期
|
||||
String token = JwtHelper.createTokenWithMap(getMap(), subject, new Date());
|
||||
System.out.println(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createToken2() {
|
||||
// 自定义 天数过期
|
||||
String token = JwtHelper.createTokenWithMap(getMap(), subject, key, new Date());
|
||||
System.out.println(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createToken3() {
|
||||
// 自定义 天数过期
|
||||
String token = JwtHelper.createTokenWithMap(getMap(), subject, key, 1);
|
||||
System.out.println(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTokenByMap() {
|
||||
// createTokenWithMap 的 token
|
||||
String createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MQQqAIBBA0btM21BHC8pVVxlsIClNzCKI7p4HaP_ffyB6t0YKDBbOg_PEN4W0sXB7gBb8DBa1aYEuKpRrtJSSrJSoR6ERhUHRD7ZTSslGuoVKRRzIb3-_9wN8w_-EbwAAAA.WFmbbjfwGycJp6-Ak8uoYdIO0R8brA8rmh5ZrG1kawI";
|
||||
createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MTQ6DIBBA4btMt_IzKgqseoLeYQSMtGKJpU0T493LAbr-Xt4BmXZKYI-zgS26x41SAAvvV9iv4Uspr4G7Z4IG6EOF9mpLKdkKga3hLSLvkCtteymluAi3UKlt9GCx7RoIieL6_3cvscI8T1orRwydUazHwTOj1cAmrzTSOKoRNZw_Uq-ijacAAAA.kOxzGz-821wJo-hRJ2FRZQ4ytLfU2JEVOSf-8EvSJLc";
|
||||
createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MQQrCMBBG4buM25BkUgWdlSfwDj_pQIMdDTEVofTu9gBdv4-3UkWDkaybo1fJzwdMSWj5aLvrD1Zn9flt5AhfdLS9Tb1XCYHTzSdmP7C_XOUcYwynkCf03ZaRhNPgSA1lPvptf8HXaaZ6AAAA.m-m4uaNM1LhyCcQyncr7tVKcNA5dAE0SLUeNI8THq7w";
|
||||
createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MTQ6CMBBA4buMW_ozpa3QlSfwDkM7hipFgtWYEO4uB3D9vbwNFlqpQNj2BuYcH1cqDAHeL14v_KWyTCzjs0AD9KFK62FjrUtQCk0vDaJsUbouWK21Oqk4Uj3anCCgaRvgQnn6_7vXfADq5J3rOtHffCusxV4MNGjB3jEm68_WGNh_tMDYSqcAAAA.G6ARBhqRNiSKHYtEdMW_Qh1d5lAa0CzgXEjlxN3NRLU";
|
||||
createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MTQ7CIBBA4buM2_IzQCuw8gTeYQqTFC3aVDQmTe9uD-D6e3kbLLRShbjtHTxKul-pMkR4v3i98JfqMrNMzwod0IcarYdNrS1RKTRBGkRpUfY-Oq21Oqk0UTvakiGisR1wpTL__91aOWDMIRtGFnq0Xrg0oBh7rwUOIZPzaPV5gP0HuCPau6cAAAA.5CGFhEz1i9RLKfFMYHA7cOg3sdfFEDZnqbBHSP9R_XY";
|
||||
createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MTQ6CMBBA4buMW_oz7VChK0_gHcZSQpUiwWpMCHe3B3D9vbwdVt44g9-PBpYUHlfOETy8X3G7xC_ndY4yPDM0wB8uvFWbSlm9Umh6aRClRdl2nrTW6qTCxKW2aQCPxjYQM6f5_-9eUgXqWzThRmKk8SzIaBSMzgnXsuuI-sFqguMH0SvcYacAAAA.qW_gqkc8RQJM-UbFVj7xldSEv1RORO4qlw6VMrTEmM0";
|
||||
createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MSw7CIBRA0b08p_yhFBi5AvfwApiiRQmiMWm6d7sAx-fmbtCwY4Ww7QQeJd4vWDMEeL9yP-cv1rZmFp8VCOAHB_bDljFa4Fwqz5SUTEs2uWCEEPzE44LjaEuCIJUmkCuW9f_vNsoBaJ1yYnZ0Rqep8VlRnESi3khrklFeXC3sP3hOgQ2nAAAA.bkPBbfpLd21eaJE2gjzniUx5n9VvCqWSY_zBiu8oO9k";
|
||||
|
||||
Map<String, Object> tokenByMap = JwtHelper.getTokenByMap(createTokenWithMapToken);
|
||||
|
||||
// 转为Java实体对戏那个
|
||||
User user = JSONObject.parseObject(JSONObject.toJSONString(tokenByMap), User.class);
|
||||
|
||||
System.out.println(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTokenByMap1() {
|
||||
String createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MSw6CMBRG4b1cp_R5i0BHrsA9_K01VKkSrMaEsHdZgOPv5Kw0Y0Ehv24NPXK8n1ESeXq_0nJKX5R5SjI-CzWEDyqW3cZaZ6-UsYO0xkg2su2901qrg4oj6t7mC3ljuaFUkKf_v1vNO8QIx51l0YIhXOicCGAnrr3trT4OgVOg7Qcl-35JpwAAAA.brAkeCBAcsRqKRbuvfrH-toHOhji6YcTaVPBYIxAdFo";
|
||||
createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MyQ3CMBBA0V6Ga7yMY8vLiQroYXBGiiGGyBiEFKV3UgDn9_U3WKlRhbTtAzxKvl-oMiR4v7id-Ut1XVjmZ4UB6EOd2mFz72tSCk2UBlGOKF1IVmutTirP1I-2TJDQjANwpbL8_916OcCbq7dkWeTAXlgfJhEnp4ULGckjZW0i7D9IMrwJpwAAAA.VmohGapOUVUNFQ9XVUX-QALeFQLad1f3Hp8NbcVZuMI";
|
||||
createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MTQ7CIBBA4buMW36nQAsrT-AdpoApWrSpaEya3t0ewPX38jZYaKUKYdsZPEq8X6hmCPB-5fWcv1SXOYv4rMCAPtRoPWxqbQlSavQCtRadFnYIRiklTzJO1I62JAgaOwa5Upn__26tHIBjTOSvxB2agRurDCeTHMceE1nne6dH2H-VOEqApwAAAA.j5BcFLT-2HENeYS8LvD27tyRnI1rE-iFzjBy1iY02T4";
|
||||
createTokenWithMapToken = "eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAA_23MTQ7CIBBA4buM2_JXWkpZeQLvMNIhRYsSRGPS9O5yANffy9shY8EEbj86eER_v2AicPB-UTnTF1PeiPtngg7wgxVLs7XW7IRQ_cx7pbhWfLRukFKKk_Ar1tbGBZzqdQeUMG7_f7caG1zlZCZDyGavFzZ4MzC0ZmIWQ1DWeBtGguMHw7854qcAAAA.V4VLIJ7vUqnfd1LeQkXa3t8V_376DWVAA_g0PE_6_S8";
|
||||
|
||||
Map<String, Object> tokenByMap = JwtHelper.getTokenByMap(createTokenWithMapToken, key);
|
||||
// 转为Java实体对戏那个
|
||||
User user = JSONObject.parseObject(JSONObject.toJSONString(tokenByMap), User.class);
|
||||
System.out.println(user);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue