token是什么?
token携带在请求头中,只有登录请求不需要携带token,登录成功后把token返回给前端,以后的请求前端需要携带这个token来才能请求成功!否则请求被拦截……
为什么要用它?
token的目的是减轻服务器压力,减少数据库请求。
如果没有token做一层拦截的,每次请求都会去请求数据库,如果恶意请求,很可能击垮数据库…
如何实现呢?
拦截器:写一个类实现HandlerInterceptor接口,重写preHandle方法,在方法里实现拦截逻辑
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 如果是OPTIONS则结束请求
if (Objects.equals(request.getMethod(), HttpMethod.OPTIONS.name())) {
response.setStatus(HttpStatus.OK.value());
return false;
}
String token = request.getHeader("token");
if (!hasText(token)) {
handleErrorResponse(response, ResponseResultEnum.PARAM_ERROR, "can't getHeader token ");
return false;
}
if (TEST_TOKEN.equals(token)) {
return true;
}
} catch (JwtException e) {
log.trace(e.getMessage(), e);
handleErrorResponse(response, ResponseResultEnum.TOKEN_INVALID);
return false;
}
return true;
}
这里的拦截,是拦截所有请求,而我们在实际开发中,要有拦截白名单,比如:登录接口
那么如何写拦截白名单呢?
写一个配置类,实现WebMvcConfigurer接口,重写addInterceptors方法
@Configuration
public class WebConfig implements WebMvcConfigurer {
private final TokenInterceptor tokenInterceptor;
public WebConfig(TokenInterceptor tokenInterceptor) {
this.tokenInterceptor = tokenInterceptor;
}
/**
* 不需拦截-白名单
*/
private static final String[] WHITELIST = {
// 登录相关
"/login/verify",
"/login/sms/**",
"/heartbeat"
};
@Override
public void addInterceptors(InterceptorRegistry registry) {
List<String> patterns = Arrays.asList(WHITELIST);
registry.addInterceptor(tokenInterceptor) // 拦截器实例
.addPathPatterns("/**") // 拦截所有请求
.excludePathPatterns(patterns); // 排除哪些请求
}
}
small tips:
1.JWT:JSON WEB TOKEN,用于生产token的插件
Jwts.builder()
.setIssuedAt(new Date())
.signWith(this.key)
.claim(Global.USER_CODE, userCode)
.claim(Global.PHONE, phone)
.claim(Global.UNION_NUM, unionNum)
.setExpiration(new Date(System.currentTimeMillis() + this.expiration))
.setId(UUID.randomUUID().toString())
.compact();
使用以上,需要导入jar包
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
token设置多久有效期?
根据具体情况来定,失效时间写在生成token的方法里,token的失效时间一般存在缓存或内存中,而不会数据库中
public String generateTokenCache(String userCode, String phone, String unionNum) {
String token = generateToken(userCode, phone, unionNum);
String key = String.format(RedisConstants.APP_TOKEN_KEY, userCode);
redisTemplate.opsForValue().set(key, ShaKit.hashString(token), this.expiration, TimeUnit.MILLISECONDS);
return token;
}