亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中JWT的使用的詳細(xì)教程

 更新時間:2023年02月09日 11:43:48   作者:ccx-lly  
JWT的本質(zhì)就是一個字符串,它是將用戶信息保存到一個Json字符串中,然后進(jìn)行編碼后得到一個JWT token,并且這個JWT token帶有簽名信息,接收后可以校驗(yàn)是否被篡改,所以可以用于在各方之間安全地將信息作為Json對象傳輸,本文介紹了Java中JWT的使用,需要的朋友可以參考下

JWT簡介

JWT全稱為Json Web Token

JWT的本質(zhì)就是一個字符串,它是將用戶信息保存到一個Json字符串中,然后進(jìn)行編碼后得到一個JWT token,并且這個JWT token帶有簽名信息,接收后可以校驗(yàn)是否被篡改,所以可以用于在各方之間安全地將信息作為Json對象傳輸。
JWT的認(rèn)證流程如下:
1 首先,前端通過Web表單將自己的用戶名和密碼發(fā)送到后端的接口,這個過程一般是一個POST請求。建議的方式是通過SSL加密的傳輸(HTTPS),從而避免敏感信息被嗅探
2 后端核對用戶名和密碼成功后,將包含用戶信息的數(shù)據(jù)作為JWT的Payload,將其與JWT Header分別進(jìn)行Base64編碼后拼接簽名,形成一個JWT Token,形成的JWT Token就是一個如同lll.zzz.xxx的字符串
3 后端將JWT Token字符串作為登錄成功的結(jié)果返回給前端。前端可以將返回的結(jié)果保存在瀏覽器中,退出登錄時刪除保存的JWT Token即可
4 前端在每次請求時將JWT Token放入HTTP請求頭中的Authorization屬性中(解決XSS和XSRF問題)
5 后端檢查前端傳過來的JWT Token,驗(yàn)證其有效性,比如檢查簽名是否正確、是否過期、token的接收方是否是自己等等
6 驗(yàn)證通過后,后端解析出JWT Token中包含的用戶信息,進(jìn)行其他邏輯操作(一般是根據(jù)用戶信息得到權(quán)限等),返回結(jié)果

JWT結(jié)構(gòu)

JWT由3部分組成:標(biāo)頭(header)、有效載荷(payLoad)、簽名(signature)。
在傳輸?shù)臅r候,會將JWT的3部分分別進(jìn)行Base64編碼后用.連接形成最終傳輸?shù)淖址?/p>

Header

JWT頭是一個描述JWT元數(shù)據(jù)的JSON對象,alg屬性表示簽名使用的算法,默認(rèn)為HMAC SHA256(寫為HS256);typ屬性表示令牌的類型,JWT令牌統(tǒng)一寫為JWT。最后,使用Base64 URL算法將上述JSON對象轉(zhuǎn)換為字符串保存

{
  "alg": "HS256",
  "typ": "JWT"
}

PayLoad

有效載荷部分,是JWT的主體內(nèi)容部分,也是一個JSON對象,包含需要傳遞的數(shù)據(jù)。 JWT指定七個默認(rèn)字段供選擇

iss:發(fā)行人
exp:到期時間
sub:主題
aud:用戶
nbf:在此之前不可用
iat:發(fā)布時間
jti:JWT ID用于標(biāo)識該JWT

除以上默認(rèn)字段外,我們還可以自定義私有字段,一般會把包含用戶信息的數(shù)據(jù)放到payload中,如下

{
  "id": "123",
  "name": "cheng"
}

Signature

簽名哈希部分是對上面兩部分?jǐn)?shù)據(jù)簽名,需要使用base64編碼后的header和payload數(shù)據(jù),通過指定的算法生成哈希,以確保數(shù)據(jù)不會被篡改。首先,需要指定一個密鑰(secret)。該密碼僅僅為保存在服務(wù)器中,并且不能向用戶公開。然后,使用header中指定的簽名算法(默認(rèn)情況下為HMAC SHA256)根據(jù)以下公式生成簽名
HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)

在計(jì)算出簽名哈希后,JWT頭,有效載荷和簽名哈希的三個部分組合成一個字符串,每個部分用.分隔,就構(gòu)成整個JWT對象

注意JWT每部分的作用,在服務(wù)端接收到客戶端發(fā)送過來的JWT token之后:
header和payload可以直接利用base64解碼出原文,從header中獲取哈希簽名的算法,從payload中獲取有效數(shù)據(jù)
signature由于使用了不可逆的加密算法,無法解碼出原文,它的作用是校驗(yàn)token有沒有被篡改。服務(wù)端獲取header中的加密算法之后,利用該算法加上secretKey對header、payload進(jìn)行加密,比對加密后的數(shù)據(jù)和客戶端發(fā)送過來的是否一致。

為了完成簽名,除了用到header信息和payload信息外,還需要算法的密鑰,也就是secretKey。加密的算法一般有2類:

  • 對稱加密:secretKey指加密密鑰,可以生成簽名與驗(yàn)簽
  • 非對稱加密:secretKey指私鑰,只用來生成簽名,不能用來驗(yàn)簽(驗(yàn)簽用的是公鑰)
    JWT的密鑰或者密鑰對,一般統(tǒng)一稱為JSON Web Key,也就是JWK
    到目前為止,jwt的簽名算法有三種:
  • HMAC【哈希消息驗(yàn)證碼(對稱)】:HS256/HS384/HS512
  • RSASSA【RSA簽名算法(非對稱)】(RS256/RS384/RS512)
  • ECDSA【橢圓曲線數(shù)據(jù)簽名算法(非對稱)】(ES256/ES384/ES512)

Java中使用JWT

我這里用的是java-jwt

引入依賴

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.10.3</version>
</dependency>

對稱簽名

生成JWT的Token

/**
     * 生成JWT token
     */
    @Test
    void generateToken(){
        //預(yù)設(shè)一個token過期時間
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.HOUR,1);//過期時間為1小時
        String token = JWT.create()
                .withHeader(new HashMap<>())//Header
                .withClaim("userId", 123)//PayLoad
                .withClaim("userName", "程")
                .withClaim("userId1", "456")
                .withExpiresAt(calendar.getTime())//過期時間
                .sign(Algorithm.HMAC256("12345"));//簽名用的密鑰secret
        System.out.println(token);
    }

利用base64解密工具來查看生成的JWT Token中header和payLoad的明文

解析JWT字符串

    /**
     * 解析jwt字符串
     */
    @Test
    void resolveToken(){
        String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWRJbnQiOjEyMywidXNlcklkU3RyaW5nIjoiNDU2IiwidXNlck5hbWUiOiLnqIsiLCJleHAiOjE2NzU5MTQzMDZ9.MNC-YCxt8C0t9SNbj3_XMRknkK3-PKBP5xX6_JLB8y8";
        //創(chuàng)建解析對象,使用的算法和secret要和創(chuàng)建token時保持一致
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("12345")).build();
        DecodedJWT decodedJWT = jwtVerifier.verify(token);
        System.out.println(decodedJWT.getPayload());//base64編碼的payLoad
        Claim userIdInt = decodedJWT.getClaim("userIdInt");
        Claim userIdString = decodedJWT.getClaim("userIdString");
        Claim userName = decodedJWT.getClaim("userName");
        System.out.println("userIdInt:"+userIdInt.asInt());
        System.out.println("userIdString:"+userIdString.asString());
        System.out.println("userName:"+userName.asString());
        System.out.println("過期時間:"+new LocalDateTime(decodedJWT.getExpiresAt()));
    }

如果我們設(shè)置的token時間短,比如設(shè)置為1秒

那么解析時為拋出如下異常

非對稱簽名

private static final String RSA_PRIVATE_KEY = "...";
private static final String RSA_PUBLIC_KEY = "...";

    /**
     * 生成token
     * @param payload token攜帶的信息
     * @return token字符串
     */
public static String getTokenRsa(Map<String,String> payload){
    // 指定token過期時間為7天
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.DATE, 7);

    JWTCreator.Builder builder = JWT.create();
    // 構(gòu)建payload
    payload.forEach((k,v) -> builder.withClaim(k,v));

    // 利用hutool創(chuàng)建RSA
    RSA rsa = new RSA(RSA_PRIVATE_KEY, null);
    // 獲取私鑰
    RSAPrivateKey privateKey = (RSAPrivateKey) rsa.getPrivateKey();
    // 簽名時傳入私鑰
    String token = builder.withExpiresAt(calendar.getTime()).sign(Algorithm.RSA256(null, privateKey));
    return token;
}

    /**
     * 解析token
     * @param token token字符串
     * @return 解析后的token
     */
public static DecodedJWT decodeRsa(String token){
    // 利用hutool創(chuàng)建RSA
    RSA rsa = new RSA(null, RSA_PUBLIC_KEY);
    // 獲取RSA公鑰
    RSAPublicKey publicKey = (RSAPublicKey) rsa.getPublicKey();
    // 驗(yàn)簽時傳入公鑰
    JWTVerifier jwtVerifier = JWT.require(Algorithm.RSA256(publicKey, null)).build();
    DecodedJWT decodedJWT = jwtVerifier.verify(token);
    return decodedJWT;
}

到此這篇關(guān)于Java中JWT的使用的文章就介紹到這了,更多相關(guān)Java中JWT使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論