SpringBoot+JWT@注解實現token驗證


原文鏈接:https://segmentfault.com/a/1190000022776284?utm_source=tag-newest

springboot集成jwt實現token驗證
1、引入jwt依賴
    <!--jwt--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.9.0</version> </dependency>
2、自定義兩個注解
/** * 忽略Token驗證 * */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface IgnoreAuth { boolean required() default true; }
/** * 登錄用戶信息 * */ @Target({ElementType.PARAMETER,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface LoginUser { boolean required() default true; } @Target:注解的作用目標 @Target(ElementType.TYPE)——接口、類、枚舉、注解 @Target(ElementType.PARAMETER)——方法參數 @Target(ElementType.METHOD)——方法 
3、定義一個用戶實體類

/** * 用戶類 * */ @Data @ApiModel(value="User對象", description="用戶表") public class User extends BaseEntity<User> { private static final long serialVersionUID=1L; @ApiModelProperty(value = "編號") private String id; @ApiModelProperty(value = "歸屬公司") private String companyId; @ApiModelProperty(value = "歸屬部門") private String officeId; @ApiModelProperty(value = "登錄名") private String loginName; @ApiModelProperty(value = "密碼") private String password; @ApiModelProperty(value = "工號") private String no; @ApiModelProperty(value = "姓名") private String name; @ApiModelProperty(value = "郵箱") private String email; @ApiModelProperty(value = "電話") private String phone; @ApiModelProperty(value = "手機") private String mobile; @ApiModelProperty(value = "用戶類型") private String userType; @ApiModelProperty(value = "用戶頭像") private String photo; @ApiModelProperty(value = "最后登陸IP") private String loginIp; @ApiModelProperty(value = "最后登陸時間",example = "2019-11-22 00:00:00") private Date loginDate; @EnumFormat @ApiModelProperty(value = "登錄狀態 : 0 正常,1 異常") private UserLoginFlagEnum loginFlag; @ApiModelProperty(value = "創建者") private String createBy; @ApiModelProperty(value = "創建時間",example = "2019-11-22 00:00:00") private Date createDate; @ApiModelProperty(value = "更新者") private String updateBy; @ApiModelProperty(value = "更新時間",example = "2019-11-22 00:00:00") private Date updateDate; @ApiModelProperty(value = "備注信息") private String remarks; @TableLogic @ApiModelProperty(value = "刪除標記") private String delFlag; @ApiModelProperty(value = "微信openid") private String openid; @Override protected Serializable pkVal() { return this.id; } } 
4、生成token
@Service("TokenService") public class TokenService { public String getToken(User user) { String token=""; token= JWT.create().withAudience(user.getId())// 將 user id 保存到 token 里面 .sign(Algorithm.HMAC256(user.getOpenid()));// 以 OpenId 作為 token 的密鑰 return token; } } 
5、設置攔截器
@Component public class AuthorizationInterceptor implements HandlerInterceptor { @Autowired IUserService userService; public static final String LOGIN_USER_KEY = "LOGIN_USER_KEY"; @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception { //支持跨域請求 httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); httpServletResponse.setHeader("Access-Control-Max-Age", "3600"); httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true"); httpServletResponse.setHeader("Access-Control-Allow-Headers", "x-requested-with,X-Nideshop-Token,X-URL-PATH"); httpServletResponse.setHeader("Access-Control-Allow-Origin", httpServletRequest.getHeader("Origin")); String token = httpServletRequest.getHeader("token");// 從 http 請求頭中取出 token // 如果不是映射到方法直接通過 if(!(object instanceof HandlerMethod)){ return true; } HandlerMethod handlerMethod=(HandlerMethod)object; Method method=handlerMethod.getMethod(); //檢查是否有IgnoreAuth注釋,有則跳過認證 if (method.isAnnotationPresent(IgnoreAuth.class)) { IgnoreAuth passToken = method.getAnnotation(IgnoreAuth.class); if (passToken.required()) { return true; } } //檢查有沒有需要用戶權限的注解 if (method.isAnnotationPresent(LoginUser.class)) { LoginUser userLoginToken = method.getAnnotation(LoginUser.class); if (userLoginToken !=null) { // 執行認證 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"); } //設置userId到request里,后續根據userId,獲取用戶信息 httpServletRequest.setAttribute(LOGIN_USER_KEY, userId); User user = userService.getById(userId); if (user == null) { throw new RuntimeException("用戶不存在,請重新登錄"); } // 驗證 token JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getOpenid())).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 { } }
6、配置攔截器

在配置類上添加了注解@Configuration,標明了該類是一個配置類並且會將該類作為一個SpringBean添加到IOC容器內

@Configuration public class InterceptorConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authenticationInterceptor()) .addPathPatterns("/**"); } @Bean public AuthenticationInterceptor authenticationInterceptor() { return new AuthenticationInterceptor(); } }
7、token驗證流程

1、用戶登錄是生成token
2、從http請求頭中取出token
3、判斷是否映射到方法
4、檢查是否有@IgnoreAuth注釋,有則跳過認證
5、檢查是否有用戶登錄的注解,有則需要取出並驗證
6、認證通過則可以訪問

  1. public class JWTUtil {  
  2.     public static final String SECRET_KEY = "123456"; //秘鑰  
  3.     public static final long TOKEN_EXPIRE_TIME = 5 * 60 * 1000; //token過期時間  
  4.     public static final long REFRESH_TOKEN_EXPIRE_TIME = 10 * 60 * 1000; //refreshToken過期時間  
  5.     private static final String ISSUER = "issuer"; //簽發人  
  6.   
  7.     /** 
  8.      * 生成簽名 
  9.      */  
  10.     public static String generateToken(String username){  
  11.         Date now = new Date();  
  12.         Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY); //算法  
  13.           
  14.         String token = JWT.create()  
  15.             .withIssuer(ISSUER) //簽發人  
  16.             .withIssuedAt(now) //簽發時間  
  17.             .withExpiresAt(new Date(now.getTime() + TOKEN_EXPIRE_TIME)) //過期時間  
  18.             .withClaim("username", username) //保存身份標識  
  19.             .sign(algorithm);  
  20.         return token;  
  21.     }  
  22.       
  23.     /** 
  24.      * 驗證token 
  25.      */  
  26.     public static boolean verify(String token){  
  27.         try {  
  28.             Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY); //算法  
  29.             JWTVerifier verifier = JWT.require(algorithm)  
  30.                     .withIssuer(ISSUER)  
  31.                     .build();  
  32.             verifier.verify(token);  
  33.             return true;  
  34.         } catch (Exception ex){  
  35.             ex.printStackTrace();  
  36.         }  
  37.         return false;  
  38.     }  
  39.       
  40.     /** 
  41.      * 從token獲取username 
  42.      */  
  43.     public static String getUsername(String token){  
  44.         try{  
  45.             return JWT.decode(token).getClaim("username").asString();  
  46.         }catch(Exception ex){  
  47.             ex.printStackTrace();  
  48.         }  
  49.         return "";  
  50.     }  
  51. }  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM