SpringBoot整合JWT框架及JWT介紹


一、傳統Session認證

1、認證過程:

1、用戶向服務器發送用戶名和密碼。 2、服務器驗證后在當前對話(session)保存相關數據。 3、服務器向返回sessionId,寫入客戶端 Cookie。 4、客戶端每次請求,需要通過 Cookie,將 sessionId 回傳服務器。 5、服務器收到 sessionId,驗證客戶端。

2、問題缺陷

1、session保存在服務端,客戶端訪問高並發時,服務端壓力大。 2、擴展性差,服務器集群,就需要 session 數據共享。

二、JWT簡介

  JWT(全稱:JSON Web Token),在基於HTTP通信過程中,進行身份認證,JWT它是目前最流行的跨域身份驗證解決方案。

1、認證流程

  JWT的工作原理:是在服務器身份驗證之后,將生成一個JSON對象,這個 JSON 對象里存了一些用戶的信息,比如id、role、name等(如:{"name": "**","role": "Admin","id":"**","Expire": "***"}),但是這個JSON對象肯定不能直接返回,所以需要加密一下,生成一個 token,就是一個加密字符串,然后將這個 token 發送回用戶之后,當用戶與服務器通信時,客戶端在請求中需要將這個 token 一起發送回服務器,服務器再解析這個 token 生成之前的JSON對象,然后去認證了這個用戶。

  當然為了防止用戶篡改數據,服務器將在生成對象時添加簽名,並對發回的數據進行驗證。

  具體流程如下:

1、客戶端通過用戶名和密碼登錄服務器; 2、服務端對客戶端身份進行驗證; 3、服務器認證以后,生成一個 JSON 對象生成的 token,發回客戶端; 4、客戶端與服務端通信的時候,都要發回這個 token; 5、服務端解析該token,然后得到這個JSON對象,獲取用戶身份; 6、服務端可以不必存儲該Token對象,身份信息都可以解析出來。

2、為什么要使用 JWT

(1)JWT基於json,非常方便解析。

(2)可以在令牌中自定義豐富的內容,易擴展。

(3)通過非對稱加密算法及數字簽名技術,JWT防止篡改,安全性高。

(4)資源服務使用JWT可不依賴認證服務即可完成授權。

3、JWT結構

  token長這樣

"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.
 eyJzdWIiOiJhZG1pbiIsImlhdCI6iZEIj3fQ. uEJSJagJf1j7A55Wwr1bGsB5YQoAyz5rbFtF"

  上面的Token被手動格式化了,實際上是用"."分隔的一個完整的長字符串,其結構如下:

1、頭部(header) 聲明類型以及加密算法; 2、負載(payload) 攜帶一些用戶身份信息; 3、簽名(signature) 簽名信息。

(1)Header:

  這個json中的typ屬性,用來標識整個token字符串是一個JWT字符串;它的alg屬性,用來說明這個JWT簽發的時候所使用的簽名和摘要算法。typ跟alg屬性的全稱其實是type跟algorithm,分別是類型跟算法的意思。

  之所以都用三個字母來表示,也是基於JWT最終字串大小的考慮,同時也是跟JWT這個名稱保持一致,這樣就都是三個字符了。

  typ跟alg是JWT中標准中規定的屬性名稱。

(2)Payload:

  payload用來承載要傳遞的數據,它的json結構實際上是對JWT要傳遞的數據的一組聲明,這些聲明被JWT標准稱為claims,它的一個“屬性值對”其實就是一個claim(要求),每一個claim的都代表特定的含義和作用。

(3)signature

  簽名是把header和payload對應的json結構進行base64url編碼之后得到的兩個串用英文句點號拼接起來,然后根據header里面alg指定的簽名算法生成出來的。算法不同,簽名結果不同。以alg: HS256為例來說明前面的簽名是以HS256算法得到。

4、JWT使用方式

  通常推薦的做法是客戶端在 HTTP 請求的頭信息Authorization字段里面:

Authorization: Bearer <token>

  服務端獲取JWT方式

String token = request.getHeader("token");

三、與SpringBoot整合

1、核心依賴文件

<!-- jjwt -->
<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.9.1</version>
</dependency>

2、配置文件

// 跟spring同級
config: jwt: # 加密密鑰 secret: TestTokenSecret // 這個自己定義
 # token有效時長 expire: 3600 # header 名稱 header: token

3、JWT配置代碼塊

@ConfigurationProperties(prefix = "config.jwt") @Component public class JwtConfig { /* * 根據身份ID標識,生成Token */
    public String getToken (String identityId){ Date nowDate = new Date(); //過期時間
        Date expireDate = new Date(nowDate.getTime() + expire * 1000); return Jwts.builder() .setHeaderParam("typ", "JWT") .setSubject(identityId) .setIssuedAt(nowDate) .setExpiration(expireDate) .signWith(SignatureAlgorithm.HS512, secret) .compact(); } /* * 獲取 Token 中注冊信息 */
    public Claims getTokenClaim (String token) { try { return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); }catch (Exception e){ e.printStackTrace(); return null; } } /* * Token 是否過期驗證 */
    public boolean isTokenExpired (Date expirationTime) { return expirationTime.before(new Date()); } private String secret; private long expire; private String header; // 省略 GET 和 SET
}

  主要是看上面加粗的一個生成token,一個解析token的方法咯。

  網上其實也有蠻多 JwtUtil 工具類,可以自己搜的參考。

四、攔截示例

  其實一般都會搭配SpringSecurity使用,這里自定義一個攔截器示例看下

1、配置Token攔截器

@Component public class TokenInterceptor extends HandlerInterceptorAdapter { @Resource private JwtConfig jwtConfig ; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 地址過濾
        String uri = request.getRequestURI() ; if (uri.contains("/login")){ return true ; } // Token 驗證
        String token = request.getHeader(jwtConfig.getHeader()); if(StringUtils.isEmpty(token)){ token = request.getParameter(jwtConfig.getHeader()); } if(StringUtils.isEmpty(token)){ throw new Exception(jwtConfig.getHeader()+ "不能為空"); } Claims claims = jwtConfig.getTokenClaim(token); if(claims == null || jwtConfig.isTokenExpired(claims.getExpiration())){ throw new Exception(jwtConfig.getHeader() + "失效,請重新登錄"); } //設置 identityId 用戶身份ID
        request.setAttribute("identityId", claims.getSubject()); return true; } }

2、攔截器注冊

@Configuration public class WebConfig implements WebMvcConfigurer { @Resource private TokenInterceptor tokenInterceptor ; public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(tokenInterceptor).addPathPatterns("/**"); } }

  然后就可以寫接口測試了。


免責聲明!

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



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