原文网址:Spring(SpringBoot)--解决拦截器中注入Bean失败的问题_IT利刃出鞘的博客-CSDN博客
简介
说明
本文用示例介绍如何解决拦截器中注入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;
- }
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |