refactor: SpringSecurity + JWT 认证鉴权重构
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
package com.youlai.system.aspect;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.exception.BusinessException;
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
import com.youlai.system.util.RequestUtils;
|
||||
import com.youlai.system.common.annotation.PreventDuplicateSubmit;
|
||||
import com.youlai.system.security.JwtTokenManager;
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
import com.youlai.system.exception.BusinessException;
|
||||
import com.youlai.system.security.jwt.JwtTokenProvider;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -25,7 +24,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* 处理重复提交的切面
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 3.0.0
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@@ -35,7 +34,7 @@ public class DuplicateSubmitAspect {
|
||||
|
||||
private final RedissonClient redissonClient;
|
||||
|
||||
private final JwtTokenManager jwtTokenManager;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
private static final String RESUBMIT_LOCK_PREFIX = "LOCK:RESUBMIT:";
|
||||
|
||||
/**
|
||||
@@ -68,9 +67,10 @@ public class DuplicateSubmitAspect {
|
||||
private String generateResubmitLockKey() {
|
||||
String resubmitLockKey = null;
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
String jwt = RequestUtils.resolveToken(request);
|
||||
if (StrUtil.isNotBlank(jwt)) {
|
||||
String jti = (String) jwtTokenManager.getTokenClaims(jwt).get("jti");
|
||||
|
||||
String token = jwtTokenProvider.resolveToken(request);
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
String jti = (String) jwtTokenProvider.getTokenClaims(token).get("jti");
|
||||
resubmitLockKey = RESUBMIT_LOCK_PREFIX + jti + ":" + request.getMethod() + "-" + request.getRequestURI();
|
||||
}
|
||||
return resubmitLockKey;
|
||||
|
||||
@@ -4,10 +4,8 @@ import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* MP数据权限注解
|
||||
* <p>
|
||||
*
|
||||
* @author zc
|
||||
* @link https://gitee.com/baomidou/mybatis-plus/issues/I37I90
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@Documented
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.youlai.system.util;
|
||||
package com.youlai.system.common.util;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.youlai.system.listener.easyexcel.MyAnalysisEventListener;
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.youlai.system.util;
|
||||
package com.youlai.system.common.util;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.youlai.system.common.result.IResultCode;
|
||||
import com.youlai.system.common.result.Result;
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
|
||||
@@ -10,6 +11,8 @@ import org.springframework.http.MediaType;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.youlai.system.common.result.ResultCode.*;
|
||||
|
||||
/**
|
||||
* 响应工具类
|
||||
*
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.youlai.system.util;
|
||||
package com.youlai.system.common.util;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.youlai.system.config;
|
||||
|
||||
import com.youlai.system.common.constant.SecurityConstants;
|
||||
import com.youlai.system.filter.JwtAuthenticationFilter;
|
||||
import com.youlai.system.security.exception.MyAccessDeniedHandler;
|
||||
import com.youlai.system.security.exception.MyAuthenticationEntryPoint;
|
||||
import com.youlai.system.security.JwtTokenManager;
|
||||
import com.youlai.system.security.jwt.JwtTokenFilter;
|
||||
import com.youlai.system.filter.VerifyCodeFilter;
|
||||
import com.youlai.system.security.jwt.JwtTokenProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -36,7 +36,7 @@ public class SecurityConfig {
|
||||
|
||||
private final MyAuthenticationEntryPoint authenticationEntryPoint;
|
||||
private final MyAccessDeniedHandler accessDeniedHandler;
|
||||
private final JwtTokenManager jwtTokenManager;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
@@ -58,7 +58,7 @@ public class SecurityConfig {
|
||||
// 验证码校验过滤器
|
||||
http.addFilterBefore(new VerifyCodeFilter(),UsernamePasswordAuthenticationFilter.class);
|
||||
// JWT 校验过滤器
|
||||
http.addFilterBefore(new JwtAuthenticationFilter(jwtTokenManager), UsernamePasswordAuthenticationFilter.class);
|
||||
http.addFilterBefore(new JwtTokenFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.youlai.system.common.constant.ExcelConstants;
|
||||
import com.youlai.system.common.result.PageResult;
|
||||
import com.youlai.system.common.result.Result;
|
||||
import com.youlai.system.util.ExcelUtils;
|
||||
import com.youlai.system.common.util.ExcelUtils;
|
||||
import com.youlai.system.common.annotation.PreventDuplicateSubmit;
|
||||
import com.youlai.system.listener.easyexcel.UserImportListener;
|
||||
import com.youlai.system.model.vo.UserImportVO;
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.youlai.system.filter;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.common.constant.SecurityConstants;
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
import com.youlai.system.util.RequestUtils;
|
||||
import com.youlai.system.util.ResponseUtils;
|
||||
import com.youlai.system.security.JwtTokenManager;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* JWT 校验过滤器
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 2022/10/1
|
||||
*/
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
private static final AntPathRequestMatcher LOGIN_PATH_REQUEST_MATCHER = new AntPathRequestMatcher(SecurityConstants.LOGIN_PATH, "POST");
|
||||
|
||||
private final JwtTokenManager tokenManager;
|
||||
|
||||
public JwtAuthenticationFilter(JwtTokenManager tokenManager) {
|
||||
this.tokenManager = tokenManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
// 登录接口放行是走过滤器链的方式(验证码校验过滤器),这里拦截到登录接口需要手动放行
|
||||
if (LOGIN_PATH_REQUEST_MATCHER.matches(request)) {
|
||||
// 手动放行登录接口
|
||||
chain.doFilter(request, response);
|
||||
}else{
|
||||
String jwt = RequestUtils.resolveToken(request);
|
||||
if (StrUtil.isNotBlank(jwt) && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
try {
|
||||
// 解析&验证 JWT
|
||||
Claims claims = this.tokenManager.parseAndValidateToken(jwt);
|
||||
|
||||
// JWT验证有效获取Authentication存入Security上下文
|
||||
Authentication authentication = this.tokenManager.getAuthentication(claims);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}catch (Exception e){
|
||||
ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID);
|
||||
}
|
||||
}else{
|
||||
ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.youlai.system.common.constant.SecurityConstants;
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
import com.youlai.system.util.ResponseUtils;
|
||||
import com.youlai.system.common.util.ResponseUtils;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
|
||||
import com.youlai.system.common.annotation.DataPermission;
|
||||
import com.youlai.system.common.base.IBaseEnum;
|
||||
import com.youlai.system.common.enums.DataScopeEnum;
|
||||
import com.youlai.system.util.SecurityUtils;
|
||||
import com.youlai.system.common.util.SecurityUtils;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package com.youlai.system.interceptor;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.common.constant.SecurityConstants;
|
||||
import com.youlai.system.security.JwtTokenManager;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import com.youlai.system.security.jwt.JwtTokenProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
@@ -25,13 +23,13 @@ import java.security.Principal;
|
||||
@RequiredArgsConstructor
|
||||
public class AuthChannelInterceptor implements ChannelInterceptor {
|
||||
|
||||
private final JwtTokenManager jwtTokenManager;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
/**
|
||||
* 连接前监听
|
||||
*
|
||||
* @param message
|
||||
* @param channel
|
||||
* @param message 消息
|
||||
* @param channel 通道
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@@ -41,14 +39,12 @@ public class AuthChannelInterceptor implements ChannelInterceptor {
|
||||
|
||||
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
|
||||
// get token from header
|
||||
String token = accessor.getFirstNativeHeader("Authorization");
|
||||
String bearerToken = accessor.getFirstNativeHeader("Authorization");
|
||||
// if token is not null
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
if (StrUtil.isNotBlank(bearerToken)) {
|
||||
|
||||
token = token.substring(SecurityConstants.TOKEN_PREFIX.length());
|
||||
Claims claims = jwtTokenManager.parseAndValidateToken(token);
|
||||
|
||||
String username = claims.get("username", String.class);
|
||||
bearerToken = bearerToken.substring(7);
|
||||
String username = jwtTokenProvider.getUsername(bearerToken);
|
||||
// if the username is not null, assign it to the Principal.
|
||||
if (StrUtil.isNotBlank(username)) {
|
||||
Principal principal = () -> username;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.youlai.system.security.exception;
|
||||
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
import com.youlai.system.util.ResponseUtils;
|
||||
import com.youlai.system.common.util.ResponseUtils;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.youlai.system.security.jwt;
|
||||
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
import com.youlai.system.common.util.ResponseUtils;
|
||||
import com.youlai.system.exception.BusinessException;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author haoxr
|
||||
* @since 2023/9/13
|
||||
*/
|
||||
public class JwtTokenFilter extends OncePerRequestFilter {
|
||||
private JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
|
||||
this.jwtTokenProvider = jwtTokenProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
String token = jwtTokenProvider.resolveToken(request);
|
||||
try {
|
||||
if (token != null && jwtTokenProvider.validateToken(token)) {
|
||||
Authentication auth = jwtTokenProvider.getAuthentication(token);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
}
|
||||
} catch (BusinessException ex) {
|
||||
//this is very important, since it guarantees the user is not authenticated at all
|
||||
SecurityContextHolder.clearContext();
|
||||
ResponseUtils.writeErrMsg(response,(ResultCode)ex.getResultCode());
|
||||
return;
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
package com.youlai.system.security;
|
||||
package com.youlai.system.security.jwt;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.youlai.system.common.constant.SecurityConstants;
|
||||
import com.youlai.system.security.model.SysUserDetails;
|
||||
import io.jsonwebtoken.*;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.io.Decoders;
|
||||
import io.jsonwebtoken.io.DecodingException;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
@@ -15,62 +19,53 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.stereotype.Component;
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* JWT token 管理器
|
||||
* JWT token 管理器
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 2022/10/22
|
||||
* @since 2023/9/13
|
||||
*/
|
||||
|
||||
@Component
|
||||
public class JwtTokenManager {
|
||||
|
||||
/**
|
||||
* token加密密钥
|
||||
*/
|
||||
@Value("${auth.token.secret_key}")
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* token有效期(单位:秒)
|
||||
*/
|
||||
@Value("${auth.token.ttl}")
|
||||
private Long tokenTtl;
|
||||
|
||||
/**
|
||||
* secret key byte array.
|
||||
*/
|
||||
private byte[] secretKeyBytes;
|
||||
|
||||
private JwtParser jwtParser;
|
||||
public class JwtTokenProvider {
|
||||
|
||||
@Resource
|
||||
private RedisTemplate redisTemplate;
|
||||
|
||||
@Value("${jwt.secret-key:123456}")
|
||||
private String secretKey;
|
||||
|
||||
@Value("${jwt.expiration:7200}")
|
||||
private int expiration;
|
||||
|
||||
private byte[] secretKeyBytes;
|
||||
|
||||
|
||||
@PostConstruct
|
||||
protected void init() {
|
||||
secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create token.
|
||||
* 创建Token
|
||||
*
|
||||
* @param authentication auth info
|
||||
* @return token
|
||||
* @param authentication
|
||||
* @return
|
||||
*/
|
||||
public String createToken(Authentication authentication) {
|
||||
Claims claims = Jwts.claims().setSubject(authentication.getName());
|
||||
|
||||
SysUserDetails userDetails = (SysUserDetails) authentication.getPrincipal();
|
||||
claims.put("jti",IdUtil.fastSimpleUUID());
|
||||
claims.put("userId", userDetails.getUserId());
|
||||
claims.put("username", claims.getSubject());
|
||||
claims.put("deptId", userDetails.getDeptId());
|
||||
claims.put("dataScope", userDetails.getDataScope());
|
||||
|
||||
// 角色放入JWT的claims
|
||||
Set<String> roles = userDetails.getAuthorities().stream()
|
||||
.map(GrantedAuthority::getAuthority).collect(Collectors.toSet());
|
||||
claims.put("authorities", roles);
|
||||
@@ -79,48 +74,57 @@ public class JwtTokenManager {
|
||||
Set<String> perms = userDetails.getPerms();
|
||||
redisTemplate.opsForValue().set(SecurityConstants.USER_PERMS_CACHE_PREFIX + userDetails.getUserId(), perms);
|
||||
|
||||
// 过期时间
|
||||
Date expirationTime = new Date(System.currentTimeMillis() + tokenTtl * 1000L);
|
||||
|
||||
Date now = new Date();
|
||||
Date expirationTime = new Date(now.getTime() + expiration * 1000L);
|
||||
return Jwts.builder()
|
||||
//.setId(IdUtil.fastSimpleUUID()) TODO 设置jti无效
|
||||
.setClaims(claims)
|
||||
.setIssuedAt(now)
|
||||
.setExpiration(expirationTime)
|
||||
.signWith(Keys.hmacShaKeyFor(this.getSecretKeyBytes()), SignatureAlgorithm.HS256).compact();
|
||||
.signWith(Keys.hmacShaKeyFor(getSecretKeyBytes()), SignatureAlgorithm.HS256).compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取认证信息
|
||||
*/
|
||||
public Authentication getAuthentication( Claims claims) {
|
||||
SysUserDetails principal = new SysUserDetails();
|
||||
principal.setUserId(Convert.toLong(claims.get("userId"))); // 用户ID
|
||||
principal.setUsername(Convert.toStr(claims.get("username"))); // 用户名
|
||||
principal.setDeptId(Convert.toLong(claims.get("deptId"))); // 部门ID
|
||||
principal.setDataScope(Convert.toInt(claims.get("dataScope"))); // 数据权限
|
||||
public Authentication getAuthentication(String token) {
|
||||
Claims claims = this.getTokenClaims(token);
|
||||
|
||||
SysUserDetails userDetails = new SysUserDetails();
|
||||
userDetails.setUserId(Convert.toLong(claims.get("userId"))); // 用户ID
|
||||
userDetails.setUsername(Convert.toStr(claims.get("username"))); // 用户名
|
||||
userDetails.setDeptId(Convert.toLong(claims.get("deptId"))); // 部门ID
|
||||
userDetails.setDataScope(Convert.toInt(claims.get("dataScope"))); // 数据权限范围
|
||||
|
||||
List<SimpleGrantedAuthority> authorities = ((ArrayList<String>) claims.get("authorities"))
|
||||
.stream()
|
||||
.map(role -> new SimpleGrantedAuthority(role))
|
||||
.collect(Collectors.toList());
|
||||
.map(SimpleGrantedAuthority::new)
|
||||
.toList();
|
||||
|
||||
return new UsernamePasswordAuthenticationToken(principal, "", authorities);
|
||||
return new UsernamePasswordAuthenticationToken(userDetails, "", authorities);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 & 验证 token
|
||||
*/
|
||||
public Claims parseAndValidateToken(String token) {
|
||||
// 解析成功说明JWT有效
|
||||
Claims claims = this.getTokenClaims(token);
|
||||
// 验证JWT 是否在黑名单(注销场景会存入黑名单)
|
||||
Boolean isBlack = redisTemplate.hasKey(SecurityConstants.BLACK_TOKEN_CACHE_PREFIX + claims.get("jti"));
|
||||
|
||||
if (isBlack) {
|
||||
throw new RuntimeException("token 已被禁用");
|
||||
public String resolveToken(HttpServletRequest req) {
|
||||
String bearerToken = req.getHeader("Authorization");
|
||||
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
|
||||
return bearerToken.substring(7);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean validateToken(String token) {
|
||||
Jwts.parserBuilder().setSigningKey(getSecretKeyBytes()).build().parseClaimsJws(token);
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getUsername(String token) {
|
||||
return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject();
|
||||
}
|
||||
|
||||
|
||||
public Claims getTokenClaims(String token) {
|
||||
Claims claims = Jwts.parserBuilder().setSigningKey(this.getSecretKeyBytes()).build().parseClaimsJws(token).getBody();
|
||||
return claims;
|
||||
}
|
||||
|
||||
|
||||
public byte[] getSecretKeyBytes() {
|
||||
if (secretKeyBytes == null) {
|
||||
try {
|
||||
@@ -133,14 +137,4 @@ public class JwtTokenManager {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get token claims
|
||||
*/
|
||||
public Claims getTokenClaims(String token) {
|
||||
if (jwtParser == null) {
|
||||
jwtParser = Jwts.parserBuilder().setSigningKey(this.getSecretKeyBytes()).build();
|
||||
}
|
||||
Claims claims = jwtParser.parseClaimsJws(token).getBody();
|
||||
return claims;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package com.youlai.system.security.service;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.common.constant.SecurityConstants;
|
||||
import com.youlai.system.util.SecurityUtils;
|
||||
import com.youlai.system.common.util.SecurityUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
|
||||
@@ -5,11 +5,10 @@ import cn.hutool.captcha.GifCaptcha;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.common.constant.SecurityConstants;
|
||||
import com.youlai.system.security.jwt.JwtTokenProvider;
|
||||
import com.youlai.system.service.AuthService;
|
||||
import com.youlai.system.util.RequestUtils;
|
||||
import com.youlai.system.model.dto.CaptchaResult;
|
||||
import com.youlai.system.model.dto.LoginResult;
|
||||
import com.youlai.system.security.JwtTokenManager;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -34,8 +33,8 @@ import java.util.concurrent.TimeUnit;
|
||||
public class AuthServiceImpl implements AuthService {
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final JwtTokenManager jwtTokenManager;
|
||||
private final RedisTemplate redisTemplate;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
@@ -49,7 +48,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
UsernamePasswordAuthenticationToken authenticationToken =
|
||||
new UsernamePasswordAuthenticationToken(username.toLowerCase().trim(), password);
|
||||
Authentication authentication = authenticationManager.authenticate(authenticationToken);
|
||||
String accessToken = jwtTokenManager.createToken(authentication);
|
||||
String accessToken = jwtTokenProvider.createToken(authentication);
|
||||
return LoginResult.builder()
|
||||
.tokenType("Bearer")
|
||||
.accessToken(accessToken)
|
||||
@@ -62,9 +61,9 @@ public class AuthServiceImpl implements AuthService {
|
||||
@Override
|
||||
public void logout() {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
String token = RequestUtils.resolveToken(request);
|
||||
String token = jwtTokenProvider.resolveToken(request);
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
Claims claims = jwtTokenManager.getTokenClaims(token);
|
||||
Claims claims = jwtTokenProvider.getTokenClaims(token);
|
||||
String jti = claims.get("jti", String.class);
|
||||
Date expiration = claims.getExpiration();
|
||||
if (expiration != null) {
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.youlai.system.model.vo.RolePageVO;
|
||||
import com.youlai.system.service.SysRoleMenuService;
|
||||
import com.youlai.system.service.SysRoleService;
|
||||
import com.youlai.system.service.SysUserRoleService;
|
||||
import com.youlai.system.util.SecurityUtils;
|
||||
import com.youlai.system.common.util.SecurityUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -11,7 +11,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.system.common.constant.SecurityConstants;
|
||||
import com.youlai.system.common.constant.SystemConstants;
|
||||
import com.youlai.system.converter.UserConverter;
|
||||
import com.youlai.system.util.SecurityUtils;
|
||||
import com.youlai.system.common.util.SecurityUtils;
|
||||
import com.youlai.system.mapper.SysUserMapper;
|
||||
import com.youlai.system.model.dto.UserAuthInfo;
|
||||
import com.youlai.system.model.bo.UserBO;
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.youlai.system.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.common.constant.SecurityConstants;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 请求工具类
|
||||
*
|
||||
* @author haoxr
|
||||
*/
|
||||
public class RequestUtils {
|
||||
|
||||
/**
|
||||
* 请求头解析获取 Token
|
||||
*/
|
||||
public static String resolveToken(HttpServletRequest request) {
|
||||
String bearerToken = request.getHeader(SecurityConstants.TOKEN_KEY);
|
||||
if (StrUtil.isNotBlank(bearerToken) && bearerToken.startsWith(SecurityConstants.TOKEN_PREFIX)) {
|
||||
return bearerToken.substring(SecurityConstants.TOKEN_PREFIX.length());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user