SpringBoot项目整合JWT对拦截器放过的请求生成token,拦截的请求校验token。达到对接口校验拦截目的。
1.增加配置
1 2 3 4 5 6
| <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.9.0</version> </dependency>
|
2.增加拦截器
1. web请求拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| package com.coder.lion.demo.config.interceptor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor; import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors;
@Configuration public class WebConfiguration implements WebMvcConfigurer {
@Autowired private TokenInterceptor tokenInterceptor;
@Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedHeaders("*") .allowedMethods("*")
.allowedOriginPatterns("*") .allowCredentials(true); }
@Override public void configureAsyncSupport(AsyncSupportConfigurer configurer) { configurer.setTaskExecutor(new ConcurrentTaskExecutor(Executors.newFixedThreadPool(3))); configurer.setDefaultTimeout(30000); }
@Override public void addInterceptors(InterceptorRegistry registry) { List<String> excludePath = new ArrayList<>(); excludePath.add("/userinfo/login"); excludePath.add("/userinfo/register"); excludePath.add("/doc.html"); excludePath.add("/swagger-ui.html"); excludePath.add("/swagger-resources/**"); excludePath.add("/v2/api-docs"); excludePath.add("/webjars/**");
registry.addInterceptor(tokenInterceptor) .addPathPatterns("/**") .excludePathPatterns(excludePath); WebMvcConfigurer.super.addInterceptors(registry);
} }
|
注意:addInterceptors方法里面需要按自己情况进行修改,excludePath集合add的是需要放行的接口路径,前几章整合了swagger,所以此处需要放行swagger相关的路径,swagger-ui.html、doc.html、swagger-resources、等等,你再加上自己想要放行的接口路径即可,一般是首页请求的接口以及登录注册的接口(不需要进行token效验的接口)。
2. token 拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| package com.coder.lion.demo.config.interceptor;
import com.alibaba.fastjson.JSONObject; import com.coder.lion.demo.utils.TokenUtils; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
@Component public class TokenInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(request.getMethod().equals("OPTIONS")){ response.setStatus(HttpServletResponse.SC_OK); return true; } response.setCharacterEncoding("utf-8"); String token = request.getHeader("token"); if (token!=null){ boolean result= TokenUtils.verify(token); if (result){ System.out.println("通过拦截器"); return true; } } response.setContentType("application/json; charset=utf-8"); try { JSONObject json=new JSONObject(); json.put("msg","token verify fail"); json.put("code","500"); response.getWriter().append(json.toString()); System.out.println("认证失败,未通过拦截器"); } catch (Exception e) { return false; }
return false; } }
|
注意:此处token从request里面获取header里面的key值是token,你要根据自己的情况来,你在前端header里面传的token叫什么名称,这里就取什么名字。
3. token 工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| package com.coder.lion.demo.utils;
import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTCreationException; import com.auth0.jwt.exceptions.JWTVerificationException; import com.auth0.jwt.interfaces.DecodedJWT; import com.coder.lion.demo.model.entity.TUser;
import java.util.Date;
public class TokenUtils {
private static final long EXPIRE_TIME= 10*60*60*1000; private static final String TOKEN_SECRET="ljdyaishijin**3nkjnj??";
public static String sign(TUser user){
String token=null; try { Date expireAt=new Date(System.currentTimeMillis()+EXPIRE_TIME); token = JWT.create() .withIssuer("auth0") .withClaim("username",user.getUsername()) .withExpiresAt(expireAt) .sign(Algorithm.HMAC256(TOKEN_SECRET)); } catch (IllegalArgumentException| JWTCreationException je) {
} return token; }
public static Boolean verify(String token){
try { JWTVerifier jwtVerifier=JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build(); DecodedJWT decodedJWT=jwtVerifier.verify(token); System.out.println("认证通过:"); System.out.println("username: " + decodedJWT.getClaim("username").asString()); System.out.println("过期时间: " + decodedJWT.getExpiresAt()); } catch (IllegalArgumentException | JWTVerificationException e) { return false; } return true; } }
|
注意:此处到期时间可以自定义按情况进行设置,1000是1秒。此处token的生成方法以及效验方法可以根据具体情况进行更改,生成token1是使用的jwt,此处验证方法存在一个用户有多个token的情况(可以同时多次登陆同一账号,重新请求token之后,前一次的token只要没有过期也能使用。),可以整合redis后进行改造(后面会讲到),可以达到一个用户只有一个token的效果(重新请求token之后,前一次的token即使没有过期也不能使用。)
3. 验证
- 未携带token,或token不正确 拦截器拦截,请求失败
- 使用web拦截器放开的接口,获取token
- 使用获取的token重新请求接口