Spring拦截器中注入Bean失败解放方案详解

网友投稿 324 2022-07-21


目录简介问题重现解决方案

简介

说明

本文用示例介绍如何解决拦截器中注入Bean失败的问题。

场景

Token拦截器中需要用@Autowired注入javaJwtUtil类,结果发现注入的JavaJwtUtil为Null。

原因

拦截器的配置类是以new JwtInterceptor的方式使用的,那么这个JwtInterceptor不受Spring管理。因此,里边@Autowired注入JavaJwtUtil是不会注入进去的。

问题重moOemCbJp现

代码

application.yml

server:  port: 8080spring:&nbmoOemCbJpsp; application:    name: springboot-jwtconfig:  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 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:8080http:///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.servmoOemCbJplet.http.HttpServletResponse;

import java.util.Arrays;

import java.util.List;

@Slf4j

public class JwtInterceptor implements HandlerInterceptor {

@Autowired

JavaJwtUtil javaJwtUtil;

List 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;

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:springboot打war包的全过程记录
下一篇:SpringBoot处理接口幂等性的两种方法详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~