1.引入jwt依赖
<!--引入JWT依赖,由于是基于Java,所以需要的是java-jwt--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency>
2.创建两个注解,PassToken和UserLoginToken,用于在项目开发中,如果需要权限校验就标注userlogintoken,如果访问的资源不需要权限验证则正常编写不需要任何注解,如果用的的请求时登录操作,在用户登录的方法上增加passtoken注解。
passtoken package com.pjb.springbootjjwt.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author jinbin * @date 2018-07-08 20:38 */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface PassToken { boolean required() default true; }
userlogintoken package com.pjb.springbootjjwt.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author jinbin * @date 2018-07-08 20:40 */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface UserLoginToken { boolean required() default true; }
注解解析:从上面我们新建的两个类上我们可以看到主要的等学习到的就四点 第一:如何创建一个注解 第二:在我们自定义注解上新增@Target注解(注解解释:这个注解标注我们定义的注解是可以作用在类上还是方法上还是属性上面) 第三:在我们自定义注解上新增@Retention注解(注解解释:作用是定义被它所注解的注解保留多久,一共有三种策略,SOURCE 被编译器忽略,CLASS 注解将会被保留在Class文件中,但在运行时并不会被VM保留。这是默认行为,所有没有用Retention注解的注解,都会采用这种策略。RUNTIME 保留至运行时。所以我们可以通过反射去获取注解信息。 第四:boolean required() default true; 默认required() 属性为true
3.服务端生成Token
4.服务端拦截请求验证Token的流程
第一步:创建拦截器,方法执行之前执行拦截
第二步:判断是否请求方法
第三步:判断方法是否是登录方法
第三步:判断是否为需要权限验证的方法
5.在项目中的应用
附上拦截器源代码
package com.pjb.springbootjjwt.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.pjb.springbootjjwt.annotation.PassToken; import com.pjb.springbootjjwt.annotation.UserLoginToken; import com.pjb.springbootjjwt.entity.User; import com.pjb.springbootjjwt.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; 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 jinbin * @date 2018-07-08 20:41 */ public class AuthenticationInterceptor implements HandlerInterceptor { @Autowired UserService userService; @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception { // 从 http 请求头中取出 token String token = httpServletRequest.getHeader("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 RuntimeException("无token,请重新登录"); } // 获取 token 中的 user id String userId; try { userId = JWT.decode(token).getAudience().get(0); } catch (JWTDecodeException j) { throw new RuntimeException("401"); } User user = userService.findUserById(userId); if (user == null) { throw new RuntimeException("用户不存在,请重新登录"); } // 验证 token JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build(); try { jwtVerifier.verify(token); } catch (JWTVerificationException e) { throw new RuntimeException("401"); } return true; } } return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } }