欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot JWT令牌的使用

 更新時(shí)間:2024年03月03日 16:35:05   作者:Big-Peng  
JWT令牌中包含了一個(gè)用戶名和哈希值,這些都需要進(jìn)行驗(yàn)證,本文主要介紹了SpringBoot JWT令牌的使用,具有一定的參考價(jià)值,感興趣的可以了解一下

介紹

JWT全稱:JSON Web Token  (官網(wǎng):https://jwt.io/

定義了一種簡潔的、自包含的格式,用于在通信雙方以json數(shù)據(jù)格式安全的傳輸信息。由于數(shù)字簽名的存在,這些信息是可靠的。

  •  簡潔:是指jwt就是一個(gè)簡單的字符串??梢栽谡埱髤?shù)或者是請求頭當(dāng)中直接傳遞。
  •  自包含:指的是jwt令牌,看似是一個(gè)隨機(jī)的字符串,但是我們是可以根據(jù)自身的需求在jwt令牌中存儲自定義的數(shù)據(jù)內(nèi)容。如:可以直接在jwt令牌中存儲用戶的相關(guān)信息。
  •  簡單來講,jwt就是將原始的json數(shù)據(jù)格式進(jìn)行了安全的封裝,這樣就可以直接基于jwt在通信雙方安全的進(jìn)行信息傳輸了。

JWT的組成: (JWT令牌由三個(gè)部分組成,三個(gè)部分之間使用英文的點(diǎn)來分割)

  • 第一部分:Header(頭), 記錄令牌類型、簽名算法等。 例如:{"alg":"HS256","type":"JWT"}
  • 第二部分:Payload(有效載荷),攜帶一些自定義信息、默認(rèn)信息等。 例如:{"id":"1","username":"Tom"}
  • 第三部分:Signature(簽名),防止Token被篡改、確保安全性。將header、payload,并加入指定秘鑰,通過指定簽名算法計(jì)算而來。

簽名的目的就是為了防jwt令牌被篡改,而正是因?yàn)閖wt令牌最后一個(gè)部分?jǐn)?shù)字簽名的存在,所以整個(gè)jwt 令牌是非常安全可靠的。一旦jwt令牌當(dāng)中任何一個(gè)部分、任何一個(gè)字符被篡改了,整個(gè)令牌在校驗(yàn)的時(shí)候都會失敗,所以它是非常安全可靠的。

JWT是如何將原始的JSON格式數(shù)據(jù),轉(zhuǎn)變?yōu)樽址哪兀?/p>

其實(shí)在生成JWT令牌時(shí),會對JSON格式的數(shù)據(jù)進(jìn)行一次編碼:進(jìn)行base64編碼

Base64:是一種基于64個(gè)可打印的字符來表示二進(jìn)制數(shù)據(jù)的編碼方式。既然能編碼,那也就意味著也能解碼。所使用的64個(gè)字符分別是A到Z、a到z、 0- 9,一個(gè)加號,一個(gè)斜杠,加起來就是64個(gè)字符。任何數(shù)據(jù)經(jīng)過base64編碼之后,最終就會通過這64個(gè)字符來表示。當(dāng)然還有一個(gè)符號,那就是等號。等號它是一個(gè)補(bǔ)位的符號

需要注意的是Base64是編碼方式,而不是加密方式。

JWT令牌最典型的應(yīng)用場景就是登錄認(rèn)證:

  • 在瀏覽器發(fā)起請求來執(zhí)行登錄操作,此時(shí)會訪問登錄的接口,如果登錄成功之后,我們需要生成一個(gè)jwt令牌,將生成的 jwt令牌返回給前端。

  • 前端拿到j(luò)wt令牌之后,會將jwt令牌存儲起來。在后續(xù)的每一次請求中都會將jwt令牌攜帶到服務(wù)端。

  • 服務(wù)端統(tǒng)一攔截請求之后,先來判斷一下這次請求有沒有把令牌帶過來,如果沒有帶過來,直接拒絕訪問,如果帶過來了,還要校驗(yàn)一下令牌是否是有效。如果有效,就直接放行進(jìn)行請求的處理。

在JWT登錄認(rèn)證的場景中我們發(fā)現(xiàn),整個(gè)流程當(dāng)中涉及到兩步操作:

  • 在登錄成功之后,要生成令牌。

  • 每一次請求當(dāng)中,要接收令牌并對令牌進(jìn)行校驗(yàn)。

生成和校驗(yàn)

首先我們先來實(shí)現(xiàn)JWT令牌的生成。要想使用JWT令牌,需要先引入JWT的依賴:

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

在引入完JWT來賴后,就可以調(diào)用工具包中提供的API來完成JWT令牌的生成和校驗(yàn)

工具類:Jwts

生成JWT代碼實(shí)現(xiàn):

@Test
public void genJwt(){
    Map<String,Object> claims = new HashMap<>();
    claims.put("id",1);
    claims.put("username","Tom");
    
    String jwt = Jwts.builder()
        .setClaims(claims) //自定義內(nèi)容(載荷)          
        .signWith(SignatureAlgorithm.HS256, "itheima") //簽名算法        
        .setExpiration(new Date(System.currentTimeMillis() + 24*3600*1000)) //有效期   
        .compact();
    
    System.out.println(jwt);
}

運(yùn)行測試方法:

eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjcyNzI5NzMwfQ.fHi0Ub8npbyt71UqLXDdLyipptLgxBUg_mSuGJtXtBk

輸出的結(jié)果就是生成的JWT令牌,,通過英文的點(diǎn)分割對三個(gè)部分進(jìn)行分割,我們可以將生成的令牌復(fù)制一下,然后打開JWT的官網(wǎng),將生成的令牌直接放在Encoded位置,此時(shí)就會自動的將令牌解析出來。

第一部分解析出來,看到JSON格式的原始數(shù)據(jù),所使用的簽名算法為HS256。

第二個(gè)部分是我們自定義的數(shù)據(jù),之前我們自定義的數(shù)據(jù)就是id,還有一個(gè)exp代表的是我們所設(shè)置的過期時(shí)間。

由于前兩個(gè)部分是base64編碼,所以是可以直接解碼出來。但最后一個(gè)部分并不是base64編碼,是經(jīng)過簽名算法計(jì)算出來的,所以最后一個(gè)部分是不會解析的。

實(shí)現(xiàn)了JWT令牌的生成,下面我們接著使用Java代碼來校驗(yàn)JWT令牌(解析生成的令牌):

@Test
public void parseJwt(){
    Claims claims = Jwts.parser()
        .setSigningKey("itheima")//指定簽名密鑰(必須保證和生成令牌時(shí)使用相同的簽名密鑰)  
	    .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjcyNzI5NzMwfQ.fHi0Ub8npbyt71UqLXDdLyipptLgxBUg_mSuGJtXtBk")
        .getBody();

    System.out.println(claims);
}

運(yùn)行測試方法:

{id=1, exp=1672729730}

令牌解析后,我們可以看到id和過期時(shí)間,如果在解析的過程當(dāng)中沒有報(bào)錯(cuò),就說明解析成功了。

下面我們做一個(gè)測試:把令牌header中的數(shù)字9變?yōu)?,運(yùn)行測試方法后發(fā)現(xiàn)報(bào)錯(cuò):

原h(huán)eader: eyJhbGciOiJIUzI1NiJ9

修改為: eyJhbGciOiJIUzI1NiJ8

結(jié)論:篡改令牌中的任何一個(gè)字符,在對令牌進(jìn)行解析時(shí)都會報(bào)錯(cuò),所以JWT令牌是非常安全可靠的。

我們繼續(xù)測試:修改生成令牌的時(shí)指定的過期時(shí)間,修改為1分鐘

@Test
public void genJwt(){
    Map<String,Object> claims = new HashMap<>();
    claims.put(“id”,1);
    claims.put(“username”,“Tom”);
    String jwt = Jwts.builder()
        .setClaims(claims) //自定義內(nèi)容(載荷)          
        .signWith(SignatureAlgorithm.HS256, “itheima”) //簽名算法        
        .setExpiration(new Date(System.currentTimeMillis() + 60*1000)) //有效期60秒   
        .compact();
    
    System.out.println(jwt);
    //輸出結(jié)果:eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjczMDA5NzU0fQ.RcVIR65AkGiax-ID6FjW60eLFH3tPTKdoK7UtE4A1ro
}

@Test
public void parseJwt(){
    Claims claims = Jwts.parser()
        .setSigningKey("itheima")//指定簽名密鑰
.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjczMDA5NzU0fQ.RcVIR65AkGiax-ID6FjW60eLFH3tPTKdoK7UtE4A1ro")
        .getBody();

    System.out.println(claims);
}

等待1分鐘之后運(yùn)行測試方法發(fā)現(xiàn)也報(bào)錯(cuò)了,說明:JWT令牌過期后,令牌就失效了,解析的為非法令牌。

通過以上測試,我們在使用JWT令牌時(shí)需要注意:

  • JWT校驗(yàn)時(shí)使用的簽名秘鑰,必須和生成JWT令牌時(shí)使用的秘鑰是配套的。

  • 如果JWT令牌解析校驗(yàn)時(shí)報(bào)錯(cuò),則說明 JWT令牌被篡改 或 失效了,令牌非法。

登錄下發(fā)令牌

JWT令牌的生成和校驗(yàn)的基本操作我們已經(jīng)學(xué)習(xí)完了,接下來我們就需要在案例當(dāng)中通過JWT令牌技術(shù)來跟蹤會話。具體的思路我們前面已經(jīng)分析過了,主要就是兩步操作:

  • 生成令牌

    • 在登錄成功之后來生成一個(gè)JWT令牌,并且把這個(gè)令牌直接返回給前端

  • 校驗(yàn)令牌

    • 攔截前端請求,從請求中獲取到令牌,對令牌進(jìn)行解析校驗(yàn)

那我們首先來完成:登錄成功之后生成JWT令牌,并且把令牌返回給前端。

實(shí)現(xiàn)步驟:

  • 引入JWT工具類

    • 在項(xiàng)目工程下創(chuàng)建com.itheima.utils包,并把提供JWT工具類復(fù)制到該包下

  • 登錄完成后,調(diào)用工具類生成JWT令牌并返回

JWT工具類

public class JwtUtils {

    private static String signKey = "itheima";//簽名密鑰
    private static Long expire = 43200000L; //有效時(shí)間

    /**
     * 生成JWT令牌
     * @param claims JWT第二部分負(fù)載 payload 中存儲的內(nèi)容
     * @return
     */
    public static String generateJwt(Map<String, Object> claims){
        String jwt = Jwts.builder()
                .addClaims(claims)//自定義信息(有效載荷)
                .signWith(SignatureAlgorithm.HS256, signKey)//簽名算法(頭部)
                .setExpiration(new Date(System.currentTimeMillis() + expire))//過期時(shí)間
                .compact();
        return jwt;
    }

    /**
     * 解析JWT令牌
     * @param jwt JWT令牌
     * @return JWT第二部分負(fù)載 payload 中存儲的內(nèi)容
     */
    public static Claims parseJWT(String jwt){
        Claims claims = Jwts.parser()
                .setSigningKey(signKey)//指定簽名密鑰
                .parseClaimsJws(jwt)//指定令牌Token
                .getBody();
        return claims;
    }
}

登錄成功,生成JWT令牌并返回 :

@RestController
@Slf4j
public class LoginController {
    //依賴業(yè)務(wù)層對象
    @Autowired
    private EmpService empService;

    @PostMapping("/login")
    public Result login(@RequestBody Emp emp) {
        //調(diào)用業(yè)務(wù)層:登錄功能
        Emp loginEmp = empService.login(emp);

        //判斷:登錄用戶是否存在
        if(loginEmp !=null ){
            //自定義信息
            Map<String , Object> claims = new HashMap<>();
            claims.put("id", loginEmp.getId());
            claims.put("username",loginEmp.getUsername());
            claims.put("name",loginEmp.getName());

            //使用JWT工具類,生成身份令牌
            String token = JwtUtils.generateJwt(claims);
            return Result.success(token);
        }
        return Result.error("用戶名或密碼錯(cuò)誤");
    }
}

重啟服務(wù),打開postman測試登錄接口:

打開瀏覽器完成前后端聯(lián)調(diào)操作:利用開發(fā)者工具,抓取一下網(wǎng)絡(luò)請求

登錄請求完成后,可以看到JWT令牌已經(jīng)響應(yīng)給了前端,此時(shí)前端就會將JWT令牌存儲在瀏覽器本地。

服務(wù)器響應(yīng)的JWT令牌存儲在本地瀏覽器哪里了呢?

  • 在當(dāng)前案例中,JWT令牌存儲在瀏覽器的本地存儲空間local storage中了。 local storage是瀏覽器的本地存儲,在移動端也是支持的。

我們在發(fā)起一個(gè)查詢部門數(shù)據(jù)的請求,此時(shí)我們可以看到在請求頭中包含一個(gè)token(JWT令牌),后續(xù)的每一次請求當(dāng)中,都會將這個(gè)令牌攜帶到服務(wù)端。

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

相關(guān)文章

  • Java利用Map實(shí)現(xiàn)計(jì)算文本中字符個(gè)數(shù)

    Java利用Map實(shí)現(xiàn)計(jì)算文本中字符個(gè)數(shù)

    這篇文章主要為大家詳細(xì)介紹了Java如何利用Map集合實(shí)現(xiàn)計(jì)算文本中字符個(gè)數(shù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-08-08
  • SpringBoot簡單的SpringBoot后端實(shí)例

    SpringBoot簡單的SpringBoot后端實(shí)例

    這篇文章主要介紹了SpringBoot簡單的SpringBoot后端實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • SpringMvc導(dǎo)出Excel實(shí)例代碼

    SpringMvc導(dǎo)出Excel實(shí)例代碼

    本篇文章主要介紹了SpringMvc導(dǎo)出Excel實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-01-01
  • Java導(dǎo)出txt文件的方法

    Java導(dǎo)出txt文件的方法

    這篇文章主要介紹了Java導(dǎo)出txt文件的方法,實(shí)例分析了兩種java導(dǎo)出txt文本文件的使用技巧,需要的朋友可以參考下
    2015-05-05
  • Java中Date和Calendar常用方法

    Java中Date和Calendar常用方法

    這篇文章主要為大家詳細(xì)介紹了Java中Date和Calendar常用用法,感興趣的小伙伴們可以參考一下
    2016-09-09
  • SpringBoot配置及使用Schedule過程解析

    SpringBoot配置及使用Schedule過程解析

    這篇文章主要介紹了SpringBoot配置及使用Schedule過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Java之網(wǎng)絡(luò)編程案例講解

    Java之網(wǎng)絡(luò)編程案例講解

    這篇文章主要介紹了Java之網(wǎng)絡(luò)編程案例講解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • Java動態(tài)代理實(shí)現(xiàn)方法小結(jié)

    Java動態(tài)代理實(shí)現(xiàn)方法小結(jié)

    這篇文章主要介紹了Java動態(tài)代理實(shí)現(xiàn)方法,結(jié)合實(shí)例形式總結(jié)分析了java基于JDK、CGLIB及CGLIB實(shí)現(xiàn)動態(tài)代理的相關(guān)操作技巧,需要的朋友可以參考下
    2019-02-02
  • Java中精確的浮點(diǎn)運(yùn)算操作示例

    Java中精確的浮點(diǎn)運(yùn)算操作示例

    這篇文章主要介紹了Java中精確的浮點(diǎn)運(yùn)算操作方法,結(jié)合具體實(shí)例形式分析了java浮點(diǎn)數(shù)運(yùn)算的相關(guān)函數(shù)、使用技巧與注意事項(xiàng),需要的朋友可以參考下
    2017-06-06
  • Struts2實(shí)現(xiàn)文件下載功能代碼分享(文件名中文轉(zhuǎn)碼)

    Struts2實(shí)現(xiàn)文件下載功能代碼分享(文件名中文轉(zhuǎn)碼)

    這篇文章主要介紹了Struts2實(shí)現(xiàn)文件下載功能代碼分享(文件名中文轉(zhuǎn)碼)的相關(guān)資料,需要的朋友可以參考下
    2016-06-06

最新評論