springboot中JJWT的簡單使用

springboot中JJWT的簡單使用

一 什麼是JWT

jwt全稱json web token,是基於json協議的用於結局認證授權的方法。token就是令牌,其主要作用是用來進行授權(Authorization),授權和認證是不同的概念,認證是系統通過賬號密碼或其他手段來驗證身份,授權是在認證後獲得系統授予的權限。系統想知道用戶有什麼權限,需要給用戶貼上標籤,方式有很多種,token是其中一種。當用戶獲得token後,用戶後續的請求只需附帶token,系統便可進行授權。jwt不同與cookie-session,它不會在服務端進行儲存,token會被寫入進http請求的header或body中進行雙向的傳輸。

JWT組成

JWT由三部分組成,分別是header,playload和signature。由於本文主要寫JJWT的使用,JWT結構就不詳細展開了,對於這部分還不瞭解的可以去JWT官網上查看,連接:JWT官網介紹

  • Header
  • PlayLoad
  • Signature

二 什麼是JJWT

JJWT旨在成爲最易於使用和理解的庫,用於在JVM和Android上創建和驗證JSON Web令牌(JWT)。 JJWT是完全基於JWT,JWS,JWE,JWK和JWA RFC規範以及Apache 2.0許可條款下的開源的純Java實現。 該圖書館由Okta的高級建築師Les Hazlewood創建,並由貢獻者社區提供支持和維護。 Okta是面向開發人員的完整身份驗證和用戶管理API。 我們還添加了一些不屬於該規範的便利擴展,例如JWS壓縮和聲明執行。

以上內容由jjwt官方文檔機翻而來

簡而言之,JJWT提供了java環境下的使用JWT的能力,使得具體實現對開發者透明,開發者只需用簡單幾行代碼即可創建或者解析一個token。

三 簡單入門

  1. 導入依賴(Maven環境)

    <!--老版本-->
    <dependency>
    	<groupId>io.jsonwebtoken</groupId>
    	<artifactId>jjwt</artifactId>
    	<version>0.9.0</version>
    </dependency>
    

    注意,現在jjwt已經更新到0.11.0,理論上說0.xx.x到0.xx.x的更新屬於兼容性的,但經過嘗試,發現還是有不少改動。這裏也貼出來最新的版本的Maven工程依賴

    <!--新版本-->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.1</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.11.1</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
        <version>0.11.1</version>
        <scope>runtime</scope>
    </dependency>
    
  2. 生成token

    jjwt中,使用Jwts.builder()進行構建token。

    // 假設代碼塊被包含在一個函數中
    Map<String, Objcet> claims = new HashMap<>();
    // claims就是playload中的內容,可以寫入自己需要的鍵值
    claims.put("key", "value");
    // 構建
    JwtBuilder jwtBuilder = Jwts.builder()
        		// 設置有效載荷
                .setClaims(claims)
        		// 設置subject
                .setSubject(subject)
        		// 設置簽發時間
                .setIssuedAt(new Date())
        		// 採用HS256方式簽名,key就是用來簽名的祕鑰
                .signWith(SignatureAlgorithm.HS256, key);
    // 調用compact函數將token打包成String並返回
    return jwtBuilder.compact();
    

    在上述代碼塊中,對JWT的playload進行了設置,沒有自定義header。

    這裏採用的HS256加密,HS256是一種對稱祕鑰加密手段,利用哈希MAC加密方式,即加密解密都使用相同的祕鑰"key"。也可以採用RS256加密或者其他加密方法,RS256是公開祕鑰加密,祕鑰分爲公鑰和私鑰,私鑰用於生成JWT,公鑰用於解密,想知道更具體的可以學習信息安全。但無論哪種加密方法,都得保護好祕鑰,並確保祕鑰難以被碰撞。

  3. 服務端發送token

    在步驟2中調用compact()會生成一長串經過編碼的字符串,字符串格式爲xxxxxx.xxxxxxxx.xxxxxxx,三個部分分別對應頭,載荷和簽名。將token發送給客戶端往往通過httpheaders中的Authorization字段發送。當然也可以放在http數據包中發送給客戶端。

    // 在header中寫入Authorization
    @RequestMapping(value = "/jwttest1", method = RequestMethod.GET)
    public String test1(HttpServletRequest request, HttpServletResponse response) {
        // 通過步驟2中的方法獲取token
        String token = ...
        response.setHeader("Authorization", token);
        return "success";
    }
    

    這裏要注意,在前端如果是跨域請求,js獲取heaer中隱私的信息在規範中是不安全的,所以服務器需設置,讓這個header暴露出來

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowCredentials(true)
                .exposedHeaders("Authorization");
    }
    
  4. 服務端解析token

    發送token後,客戶端的請求會附帶token,token同樣可以放httpheader中或報文中,接下來需要解析token

    @RequestMapping(value = "/jwttest2", method = RequestMethod.GET)
    public void test2(HttpServletRequest request, HttpServletResponse response) {
        String token = request.getHeader("Authorization");
        // 調用下面寫的方法解析即可,由於沒有寫方法的類,這裏就不演示了
    }
    
    // 解析token
    public Claims jwtParser(String token) {
        Claims claims;
        // token不一定通過驗證,所以需要包裹try-catch捕獲jjwt提供的JwtException
        try {
            claims = Jwts.parser()
            	// HS256是對稱加密體系,加密解密使用同一個key
                .setSigningKey(key)
                .parseClaimsJws(token)
                .getBody();
        } catch (JwtException e) {
            claims = null;
            e.printStackTrace();
        }
        return claims;
    }
    

    獲取到的claims就是playload,如果是playload中的標準字段可以直接通過函數取出如

    String subject = (String) claims.getSubject();
    

    如果是自己自定義的鍵值可以通過get()方法取出,假設儲存的值可以轉換String

    String value = (String) claims.get("key");
    

    這樣就獲取到並解析了token。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章