========================
开发记录:拦截器配置笔记(token认证拦截器和JWT校验拦截器)
1、创建配置类WebInterceptorConfig实现WebMvcConfigurer;
2、向InterceptorRegistry中依次注册拦截器;
3、总结:多个拦截器的执行顺序
1. 配置类WebInterceptorConfig
package com.tal.markms.config;
import com.tal.markms.interceptor.AuthenticationInterceptor;
import com.tal.markms.interceptor.JWTInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebInterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthenticationInterceptor())
.addPathPatterns("/markms/login");
registry.addInterceptor(new JWTInterceptor())
.addPathPatterns("/**").excludePathPatterns("/markms/login");
}
}
2.1 创建AuthenticationInterceptor拦截器
package com.tal.markms.interceptor;
import com.tal.markms.exception.BizException;
import com.tal.markms.exception.ErrorCode;
import com.tal.markms.utils.EmptyHelper;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;
import static com.tal.markms.common.CommonConstant.RPCID;
import static com.tal.markms.common.CommonConstant.TRACEID;
@Slf4j
@Component
public class AuthenticationInterceptor implements HandlerInterceptor {
private static String token;
@Value("${server-access.token}")
public void setToken(String token) {
AuthenticationInterceptor.token = token;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("AuthenticationInterceptor preHandle start ==== ");
MDC.put("startTime", String.valueOf(System.currentTimeMillis()));
String token = request.getHeader("token");
if (EmptyHelper.isEmpty(token)) {
log.info(" token is null ==== ");
throw new BizException(ErrorCode.SystemError.ERROR_TOKEN_NULL);
}
if (!token.equals(AuthenticationInterceptor.token)) {
log.info(" token is not match ==== ");
throw new BizException(ErrorCode.SystemError.ERROR_TOKEN_NOT_MATCH);
}
String traceId = request.getHeader(TRACEID);
if (EmptyHelper.isEmpty(traceId)) {
traceId = UUID.randomUUID().toString().replace("-", "");
log.info("traceId is null, generate traceId: {} ", traceId);
}
log.info("traceId:{}", traceId);
MDC.put("traceId", traceId);
String rpcId = request.getHeader(RPCID);
if (EmptyHelper.isEmpty(rpcId)) {
rpcId = "1.1";
log.info("rpcId is null, generate rpcId: {} ", rpcId);
}
MDC.put("rpcId", rpcId);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("responseEnd, useTime:{}", System.currentTimeMillis() - Long.parseLong(MDC.get("startTime")));
MDC.clear();
}
}
2.2 创建JWTInterceptor拦截器
package com.tal.markms.interceptor;
import com.tal.markms.config.JWTWebConfig;
import com.tal.markms.utils.JWTUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class JWTInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) {
try {
String token = httpServletRequest.getHeader("JWT");
if (token == null) {
refuseResult(httpServletResponse);
return false;
}
if(!JWTUtils.verify(token)){
//先检查并更新 后用更新后的再次校验
if(JWTWebConfig.checkAndRefreshSecretKey()||!JWTUtils.verify(token)){
refuseResult(httpServletResponse);
return false;
}
}
return true;
}catch (Exception e){
try {
refuseResult(httpServletResponse);
return false;
}catch (Exception exception){
return false;
}
}
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
public void refuseResult(HttpServletResponse httpServletResponse){
try {
httpServletResponse.setContentType("text/html;charset=UTF-8");
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setStatus(200);
httpServletResponse.getWriter().print("{\"code\":2001,\"message\":\"登录信息有误或已失效,请重新登录\"}");
httpServletResponse.getWriter().flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
创建JWT配置类设置JWT公钥、私钥、加密算法、过期时间:
package com.tal.markms.config;
import com.auth0.jwt.algorithms.Algorithm;
import com.tal.markms.enums.EnvEnum;
import com.tal.markms.factory.AlgorithmFactory;
import com.tal.markms.interceptor.JWTInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.json.JacksonJsonParser;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
@Configuration
public class JWTWebConfig implements WebMvcConfigurer {
public static String PUBLIC_KEY = "2580eb1e23fa21a84117bbd865f038a5";
public static String PRIVATE_KEY = "2580eb1e23fa21a84117bbd865f038a5";
public static final long EXPIRES_TIME = 60*60*1000*24*5L;
@Value("${jwt.interceptor.paths:}")
String interceptorPaths;
@Value("${jwt.interceptor.exclude.paths:}")
String excludePaths;
@Value("${jwt.algorithm:}")
String algorithmStr;
public static String url;
private static Algorithm algorithm;
EnvEnum envEnum;
@Value("${jwt.public_key:}")
public void setPublicKey(String arg){
PUBLIC_KEY =arg;
}
@Value("${jwt.private_key:}")
public void setPrivateKey(String arg){
PRIVATE_KEY =arg;
}
@Value("${jwt.url:}")
public void setURL(String arg){
url=arg;
}
@Value("${jwt.env:}")
public void setEnv(String env) {
if(env == null || "".equals(env)){
env = "DEV";
}
envEnum = EnvEnum.valueOf(env.toUpperCase());
}
@PostConstruct
protected void init() throws Exception {
if(!EnvEnum.OTHER.equals(envEnum)){
url = envEnum.getKeyURL();
}
//other环境下不配置url不会更新public_key 以配置文件为主
if(url == null||"".equals(url)) {
algorithm = AlgorithmFactory.getInstance(algorithmStr, PUBLIC_KEY,PRIVATE_KEY);
}
checkAndRefreshSecretKey();
System.out.println("JWT url load success, url is "+url);
System.out.println("JWT SECRET_KEY load success, key is "+ PUBLIC_KEY);
}
public static boolean checkAndRefreshSecretKey(){
try {
if(url == null || "".equals(url)) {
return true;
}
String str = getSecretKey(url);
JacksonJsonParser parser = new JacksonJsonParser();
Map result = parser.parseMap(str);
Map dataMap = (Map)result.get("data");
String newPublicKey = (String)dataMap.get("publicKey");
String algorithmName = (String)dataMap.get("algorithm");
if(PUBLIC_KEY.equals(newPublicKey)) {
return true;
}
PUBLIC_KEY = newPublicKey;
algorithm = AlgorithmFactory.getInstance(algorithmName, PUBLIC_KEY,null);
return false;
}catch (Exception e){
e.printStackTrace();
return false;
}
}
public static String getSecretKey(String urlStr){
if(urlStr == null||"".equals(urlStr)) {
return null;
}
String result = "";
BufferedReader in = null;
try {
URL url = new URL(urlStr);
// 打开和URL之间的连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
// 建立实际的连接
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
System.out.println("connect failed for code " + connection.getResponseCode());
return null;
}
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
return result;
} catch (Exception e) {
System.out.println("JWT SECRET_KEY get failed" + e);
e.printStackTrace();
return null;
} finally {
// 使用finally块来关闭输入流
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
public static Algorithm getAlgorithm(){
return algorithm;
}
/**
* 添加jwt拦截器
* @param registry
*/
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration registration = null;
if(!(interceptorPaths == null||"".equals(interceptorPaths))) {
registration = registry.addInterceptor(JWTInterceptor());
System.out.println("加载拦截器 路径为="+interceptorPaths);
String[] interceptorPathArray=interceptorPaths.split(",");
registration.addPathPatterns(interceptorPathArray);
}
if(!(excludePaths == null||"".equals(excludePaths))) {
System.out.println("加载拦截器 排除路径="+excludePaths);
String[] excludePathArray=excludePaths.split(",");
registration.excludePathPatterns(excludePathArray);
}
}
/**
* jwt拦截器
* @return
*/
@Bean
public JWTInterceptor JWTInterceptor() {
return new JWTInterceptor();
}
}
注意:在 Spring 配置中添加了多个拦截器,拦截器的执行顺序如下:
- preHandle 方法
preHandle 方法是按照配置的顺序依次执行的。
如果某个 preHandle 方法返回 false,那么后续的 preHandle 不会被执行,请求也不会到达控制器。 - postHandle 和 afterCompletion 方法
postHandle 和 afterCompletion 方法的执行顺序与 preHandle 相反,即按照配置顺序的倒序执行。
这是因为 postHandle 和 afterCompletion 负责处理响应,在处理完请求后再逆序执行。 - 异常处理
如果在拦截器链中或控制器中抛出异常,afterCompletion 方法仍然会被执行,用于进行资源清理等操作。
示例
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new Interceptor1());
registry.addInterceptor(new Interceptor2());
registry.addInterceptor(new Interceptor3());
}
}
- 执行顺序:
preHandle: Interceptor1 -> Interceptor2 -> Interceptor3
postHandle: Interceptor3 -> Interceptor2 -> Interceptor1
afterCompletion: Interceptor3 -> Interceptor2 -> Interceptor1
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » Java中的拦截器配置-- HandlerInterceptor
发表评论 取消回复