日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JAVA 实现 JWT

發布時間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA 实现 JWT 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 引入JWT依賴,由于是基于Java,所以需要的是java-jwt
  • <dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version> </dependency>
  • 自定義注解用于判斷是否需要驗證
    • 用來跳過驗證的PassToken
    @Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface PassToken {boolean required() default true;}
    • 需要登錄才能進行操作的注解UserLoginToken
    @Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface UserLoginToken {boolean required() default true;}

    @Target:注解的作用目標

    • @Target(ElementType.TYPE)——接口、類、枚舉、注解
    • @Target(ElementType.FIELD)——字段、枚舉的常量
    • @Target(ElementType.METHOD)——方法
    • @Target(ElementType.PARAMETER)——方法參數
    • @Target(ElementType.CONSTRUCTOR) ——構造函數
    • @Target(ElementType.LOCAL_VARIABLE)——局部變量
    • @Target(ElementType.ANNOTATION_TYPE)——注解
    • @Target(ElementType.PACKAGE)——包
      @Retention:注解的保留位置
      RetentionPolicy.SOURCE:這種類型的Annotations只在源代碼級別保留,編譯時就會被忽略,在class字節碼文件中不包含。 RetentionPolicy.CLASS:這種類型的Annotations編譯時被保留,默認的保留策略,在class文件中存在,但JVM將會忽略,運行時無法獲得。 RetentionPolicy.RUNTIME:這種類型的Annotations將被JVM保留,所以他們能在運行時被JVM或其他使用反射機制的代碼所讀取和使用。
      @Document:說明該注解將被包含在javadoc中
      @Inherited:說明子類可以繼承父類中的該注解

    3.編寫token的生成方法

    • 生成不攜帶自定義信息的 JWT token
  • 構建頭部信息
  • Map<String, Object> map = new HashMap<String, Object>();map.put("alg", "HS256");map.put("typ", "JWT");
  • 構建密鑰信息
  • Algorithm algorithm = Algorithm.HMAC256("secret");

    Algorithm.HMAC256(): 使 HS256 生token,唯一密鑰可以保存在服務端。“secret” 為相應的密鑰

  • 我們通過定義注冊和自定義聲明 并組合頭部信息和密鑰信息生成jwt token
  • String token = JWT.create().withHeader(map)// 設置頭部信息 Header .withIssuer("SERVICE")//設置 載荷 簽名是有誰生成 例如 服務器.withSubject("this is test token")//設置 載荷 簽名的主題// .withNotBefore(new Date())//設置 載荷 定義在什么時間之前,該jwt都是不可用的..withAudience("APP")//設置 載荷 簽名的觀眾 也可以理解誰接受簽名的.withIssuedAt(nowDate) //設置 載荷 生成簽名的時間.withExpiresAt(expireDate)//設置 載荷 簽名過期的時間.sign(algorithm);//簽名 Signature
    • 生成攜帶自定義信息的 JWT token
      自定義信息通過 withClaim 方法進行添加,具體操作如下:
    JWT.create().withHeader(map).withClaim("key", "value")
  • 驗證 JWT token
    • 構建密鑰信息
    Algorithm algorithm = Algorithm.HMAC256("secret");
    • 通過密鑰信息和簽名的發布者的信息生成 JWTVerifier (JWT驗證類)
    JWTVerifier verifier = JWT.require(algorithm).withIssuer("SERVICE").build();

    不添加 .withIssuer(“SERVICE”) 也是可以獲取 JWTVerifier 。

    • 通過 JWTVerifier 的verify獲取 token中的信息。
    DecodedJWT jwt = verifier.verify(token);

    如下面代碼所示就可以獲取到我們之前生成 token 的 簽名的主題,觀眾 和自定義的聲明信息。

    String subject = jwt.getSubject();//獲得簽名主題List<String> audience = jwt.getAudience();//獲得簽名接收方Map<String, Claim> claims = jwt.getClaims();//獲得自定義信息for (Entry<String, Claim> entry : claims.entrySet()) {String key = entry.getKey();Claim claim = entry.getValue();System.out.println("key:"+key+" value:"+claim.asString());}
  • 編寫攔截器 interceptor
  • public class AuthenticationInterceptor implements HandlerInterceptor {@AutowiredUserService userService;@Overridepublic boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object object) throws IOException {String token = req.getHeader("token");// 從 http 請求頭中取出 token// 如果不是映射到方法直接通過if(!(object instanceof HandlerMethod)){return true;}//獲得控制器函數所在的控制器類HandlerMethod handlerMethod = (HandlerMethod)object;//獲得控制器函數Method method = handlerMethod.getMethod();//獲得控制器函數所在的控制器類的ClassClass controllerClass = handlerMethod.getBean().getClass();//檢查類中是否有跳過認證的注解if(controllerClass.isAnnotationPresent(PassToken.class)){PassToken passToken = (PassToken) controllerClass.getAnnotation(PassToken.class);if (passToken.required()) {return true;}}//檢查方法是否有passtoken注釋,有則跳過認證if (method.isAnnotationPresent(PassToken.class)) {PassToken passToken = method.getAnnotation(PassToken.class);if (passToken.required()) {return true;}}//判斷類中是否有登陸注解if(controllerClass.isAnnotationPresent(UserLoginToken.class)){UserLoginToken userLoginToken = (UserLoginToken);controllerClass.getAnnotation(UserLoginToken.class);//驗證tokenneedUserLogin(userLoginToken, token);}//判斷方法中是否有登陸的注解if(method.isAnnotationPresent(UserLoginToken.class)){UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);//驗證tokenneedUserLogin(userLoginToken, token);}return true;}//驗證注解的函數public boolean needUserLogin(UserLoginToken userLoginToken, String token){if(userLoginToken.required()){//需要驗證if(token == null){throw new RuntimeException("無token, 請重新登陸");}String un;try{//獲取簽名接受方un = JWT.decode(token).getAudience().get(0);}catch (JWTDecodeException j) {throw new RuntimeException("401");}//通過用戶名獲取用戶信息User user = userService.findUserByUn(un);if(user == null){throw new RuntimeException("用戶不存在,請重新登陸");}// 通過生成算法及密鑰生成 token驗證類JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPd())).build();try {//驗證 token,驗證錯誤或token超時會拋出異常jwtVerifier.verify(token);} catch (JWTVerificationException e) {throw new RuntimeException("401");}return true;}return true;} }

    實現一個攔截器就需要實現HandlerInterceptor接口

    HandlerInterceptor接口主要定義了三個方法

    • boolean preHandle (): 預處理回調方法,實現處理器的預處理,第三個參數為響應的處理器,自定義Controller,返回值為true表示繼續流程(如調用下一個攔截器或處理器)或者接著執行 postHandle()和afterCompletion();false表示流程中斷,不會繼續調用其他的攔截器或處理器,中斷執行。
    • void postHandle(): 后處理回調方法,實現處理器的后處理(DispatcherServlet進行視圖返回渲染之前進行調用),此時我們可以通過modelAndView(模型和視圖對象)對模型數據進行處理或對視圖進行處理,modelAndView也可能為null。
    • void afterCompletion(): 整個請求處理完畢回調方法,該方法也是需要當前對應的Interceptor的preHandle()的返回值為true時才會執行,也就是在DispatcherServlet渲染了對應的視圖之后執行。用于進行資源清理。整個請求處理完畢回調方法。如性能監控中我們可以在此記錄結束時間并輸出消耗時間,還可以進行一些資源清理,類似于try-catch-finally中的finally,但僅調用處理器執行鏈中
      主要流程:
      1.從 http 請求頭中取出 token
      2.判斷是否映射到方法或控制器類
      3.檢查是否有passtoken注釋,有則跳過認證
      4.檢查有沒有需要用戶登錄的注解,有則需要取出并驗證
      5.認證通過則可以訪問,不通過會報相關錯誤信息

    6.注冊攔截器

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

    @Configuration public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(authenticationInterceptor()).addPathPatterns("/**"); // 攔截所有請求,通過判斷是否有 @UserLoginToken 注解 決定是否需要登錄}@Beanpublic AuthenticationInterceptor authenticationInterceptor() {return new AuthenticationInterceptor();} }

    總結

    JWT 就是一個生成 Token 的工具,如果不使用 JWT 我們也可以根據自己加密規則生成 Token。只不過 JWT 規范了生成 Token 定義了一個標準而已。JWT 的核心的功能就是:生成Token、解析Token。

    參考博客:

    • https://blog.csdn.net/ljk126wy/article/details/82751787
    • https://www.jianshu.com/p/e88d3f8151db

    總結

    以上是生活随笔為你收集整理的JAVA 实现 JWT的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。