梗概:
JWT意思是Json web token,通过POST参数或者在HTTP header发送,然后进行验证,验证通过之后,就能返回响应的资源给浏览器。
1、引入依赖:
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
2、自定义两个注解
2.1 用来跳过验证的PassToken
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
boolean required() default true;
}
2.2 需要登录才能进行操作的注解UserLoginToken
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
boolean required() default true;
}
3、 封装生成Token的工具类
public class JWTUtils {
public static String getToken(String userId, String mobile) {
return JWT.create()
.withAudience(userId)
.sign(Algorithm.HMAC256(mobile));
}
}
4、新增一个拦截器AuthenticationInterceptor
package com.ruoyi.framework.interceptor;
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.ruoyi.common.exception.AppUserLoginException;
import com.ruoyi.system.domain.TAppUser;
import com.ruoyi.system.mapper.TAppUserMapper;
import com.ruoyi.system.service.ITAppUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
/**
* @author 蔡志健
* @date 2021/1/7 22:18
**/
public class AuthenticationInterceptor implements HandlerInterceptor {
@Autowired
private TAppUserMapper tAppUserMapper;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token
// 如果不是映射到方法直接通过
if (!(object instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) object;
Method method = handlerMethod.getMethod();
//检查是否有passtoken注释,有则跳过认证
if (method.isAnnotationPresent(PassToken.class)) {
PassToken passToken = method.getAnnotation(PassToken.class);
if (passToken.required()) {
return true;
}
}
//检查有没有需要用户权限的注解
if (method.isAnnotationPresent(UserLoginToken.class)) {
UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
if (userLoginToken.required()) {
// 执行认证
if (token == null) {
throw new AppUserLoginException("无token,请重新登录");
}
// 获取 token 中的 user id
String userId;
try {
userId = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
throw new AppUserLoginException("token验证失败");
}
TAppUser user = tAppUserMapper.selectTAppUserByUserId(userId);
if (user == null) {
throw new AppUserLoginException("用户不存在,请重新登录");
}
// 验证 token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getMobile())).build();
try {
jwtVerifier.verify(token);
} catch (JWTVerificationException e) {
throw new AppUserLoginException("token验证失败");
}
return true;
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o, ModelAndView modelAndView) {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o, Exception e) {
}
}
备注:
- TAppUserMapper 对应自己的Mapper
- AppUserLoginException是自己封装的异常类
5、配置拦截器
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor())
.addPathPatterns("/**");
}
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
}
6、验证
不加注解的话默认不验证,登录接口一般是不验证的。在getMessage()中我加上了登录注解,说明该接口必须登录获取token后,在请求头中加上token并通过验证才可以访问
6.1 不进行token验证
@RequestMapping("/login")
public AjaxResult loginByCode(@RequestParam("mobile") String mobile, @RequestParam("code") String code) {
...业务逻辑...
return AjaxResult.success("success", tAppUser);
}
6.2 进行token验证
@UserLoginToken
@RequestMapping("/info")
public AjaxResult selectTAppUserByUserId(@RequestParam("userId") String userId) {
return itAppUserService.selectTAppUserByUserId(userId);
}
请求示例:
header中放进token










网友评论