这两天遇到SpringBoot拦截器中Bean无法注入问题。下面介绍关于SpringBoot拦截器中Bean无法注入的问题解决方案,感兴趣的朋友一起看看吧
简介
说明
本文用示例介绍如何解决拦截器中注入Bean失败的问题。
场景
Token拦截器中需要用@Autowired注入JavaJwtUtil类,结果发现注入的JavaJwtUtil为Null。
原因
拦截器的配置类是以new JwtInterceptor的方式使用的,那么这个JwtInterceptor不受Spring管理。因此,里边@Autowired注入JavaJwtUtil是不会注入进去的。
问题重现
代码
application.yml
server:
port: 8080
spring:
application:
name: springboot-jwt
config:
jwt:
# 密钥
secret: abcd1234
# token过期时间(5分钟)。单位:毫秒.
expire: 300000
拦截器配置
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JwtInterceptor());
}
}
拦截器
package com.example.demo.interceptor;
import com.example.demo.util.JavaJwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
@Slf4j
@Component
public class JwtInterceptor implements HandlerInterceptor {
@Autowired
JavaJwtUtil javaJwtUtil;
List<String> whiteList = Arrays.asList(
"/auth/login",
"/error"
);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
// 如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) {
return true;
}
//放过不需要验证的页面。
String uri = request.getRequestURI();
if (whiteList.contains(uri)) {
return true;
}
// 头部和参数都查看一下是否有token
String token = request.getHeader("token");
if (StringUtils.isEmpty(token)) {
token = request.getParameter("token");
if (StringUtils.isEmpty(token)) {
throw new RuntimeException("token是空的");
}
}
if (!javaJwtUtil.verifyToken(token)) {
log.error("token无效");
return false;
}
String userId = javaJwtUtil.getUserIdByToken(token);
log.info("userId:" + userId);
String userName = javaJwtUtil.getUserNameByToken(token);
log.info("userName:" + userName);
return true;
}
}
Jwt工具类
package com.example.demo.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class JavaJwtUtil {
//过期时间
@Value("${config.jwt.expire}")
private Long EXPIRE_TIME;
//密钥
@Value("${config.jwt.secret}")
private String SECRET;
// 生成Token,五分钟后过期
public String createToken(String userId) {
try {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(SECRET);
return JWT.create()
// 将 user id 保存到 token 里面
.withAudience(userId)
// date之后,token过期
.withExpiresAt(date)
// token 的密钥
.sign(algorithm);
} catch (Exception e) {
return null;
}
}
// 根据token获取userId
public String getUserIdByToken(String token) {
try {
String userId = JWT.decode(token).getAudience().get(0);
return userId;
} catch (JWTDecodeException e) {
return null;
}
}
// 根据token获取userName
public String getUserNameByToken(String token) {
try {
String userName = JWT.decode(token).getSubject();
return userName;
} catch (JWTDecodeException e) {
return null;
}
}
//校验token
public boolean verifyToken(String token) {
try {
Algorithm algorithm = Algorithm.HMAC256(SECRET);
JWTVerifier verifier = JWT.require(algorithm)
// .withIssuer("auth0")
// .withClaim("username", username)
.build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (JWTVerificationException exception) {
// throw new RuntimeException("token 无效,请重新获取");
return false;
}
}
}
Controller
package com.example.demo.controller;
import com.example.demo.util.JavaJwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
JavaJwtUtil javaJwtUtil;
@RequestMapping("/login")
public String login() {
// 验证userName,password和数据库中是否一致,如不一致,直接返回失败
// 通过userName,password从数据库中获取userId
String userId = 5 + "";
String token = javaJwtUtil.createToken(userId);
System.out.println("token:" + token);
return token;
}
//需要token验证
@RequestMapping("/info")
public String info() {
return "验证通过";
}
}
测试
访问:http://localhost:8080/auth/login
前端结果:一串token字符串
访问:http://localhost:8080/auth/info(以token作为header或者参数)
后端结果
java.lang.NullPointerException: null
at com.example.demo.interceptor.JwtInterceptor.preHandle(JwtInterceptor.java:55) ~[main/:na]
解决方案
方案简述
配置类中将new JwtInterceptor()改为Bean的方式
配置类
package com.example.demo.interceptor;
import org.springframework.context.annotation.Bean;
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 InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getJwtInterceptor());
}
@Bean
JwtInterceptor getJwtInterceptor() {
return new JwtInterceptor();
}
}
拦截器(此时无需@Component)
package com.example.demo.interceptor;
import com.example.demo.util.JavaJwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {
@Autowired
JavaJwtUtil javaJwtUtil;
List<String> whiteList = Arrays.asList(
"/auth/login",
"/error"
);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
// 如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) {
return true;
}
//放过不需要验证的页面。
String uri = request.getRequestURI();
if (whiteList.contains(uri)) {
return true;
}
// 头部和参数都查看一下是否有token
String token = request.getHeader("token");
if (StringUtils.isEmpty(token)) {
token = request.getParameter("token");
if (StringUtils.isEmpty(token)) {
throw new RuntimeException("token是空的");
}
}
if (!javaJwtUtil.verifyToken(token)) {
log.error("token无效");
return false;
}
String userId = javaJwtUtil.getUserIdByToken(token);
log.info("userId:" + userId);
String userName = javaJwtUtil.getUserNameByToken(token);
log.info("userName:" + userName);
return true;
}
}
到此这篇关于Spring拦截器中注入Bean失败解放方案详解的文章就介绍到这了,更多相关Spring Bean内容请搜索编程学习网以前的文章希望大家以后多多支持编程学习网!
本文标题为:Spring拦截器中注入Bean失败解放方案详解
基础教程推荐
- java基础知识之FileInputStream流的使用 2023-08-11
- Java并发编程进阶之线程控制篇 2023-03-07
- Java文件管理操作的知识点整理 2023-05-19
- springboot自定义starter方法及注解实例 2023-03-31
- JDK数组阻塞队列源码深入分析总结 2023-04-18
- Java实现线程插队的示例代码 2022-09-03
- java实现多人聊天系统 2023-05-19
- Java实现查找文件和替换文件内容 2023-04-06
- ConditionalOnProperty配置swagger不生效问题及解决 2023-01-02
- Java数据结构之对象比较详解 2023-03-07