最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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í)就會自動(dòng)的將令牌解析出來。

第一部分解析出來,看到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是瀏覽器的本地存儲,在移動(dòng)端也是支持的。

我們在發(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 AOP實(shí)現(xiàn)自定義滑動(dòng)窗口限流器方法詳解

    Java AOP實(shí)現(xiàn)自定義滑動(dòng)窗口限流器方法詳解

    這篇文章主要介紹了Java AOP實(shí)現(xiàn)自定義滑動(dòng)窗口限流器方法,其中滑動(dòng)窗口算法彌補(bǔ)了計(jì)數(shù)器算法的不足,滑動(dòng)窗口算法把間隔時(shí)間劃分成更小的粒度,當(dāng)更小粒度的時(shí)間間隔過去后,把過去的間隔請求數(shù)減掉,再補(bǔ)充一個(gè)空的時(shí)間間隔,需要的朋友可以參考下
    2022-07-07
  • 一文徹底吃透SpringMVC中的轉(zhuǎn)發(fā)和重定向

    一文徹底吃透SpringMVC中的轉(zhuǎn)發(fā)和重定向

    大家應(yīng)該都知道springmvc本來就會把返回的字符串作為視圖名解析,然后轉(zhuǎn)發(fā)到對應(yīng)的視圖,這篇文章主要給大家介紹了關(guān)于SpringMVC中轉(zhuǎn)發(fā)和重定向的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • springboot項(xiàng)目配置swagger2示例詳解

    springboot項(xiàng)目配置swagger2示例詳解

    Swagger是一款RESTful接口的文檔在線自動(dòng)生成、功能測試功能框架。本文重點(diǎn)給大家介紹springboot項(xiàng)目配置swagger2示例代碼詳解,需要的朋友參考下吧
    2021-09-09
  • 三分鐘快速掌握J(rèn)ava中枚舉(enum)

    三分鐘快速掌握J(rèn)ava中枚舉(enum)

    enum的全稱為enumeration, 是 JDK 1.5中引入的新特性,存放在 java.lang包中。下面這篇文章是我在使用enum過程中的一些經(jīng)驗(yàn)和總結(jié),分享出來方便大家快速的掌握J(rèn)ava中枚舉(enum),有需要的朋友們下面跟著小編來一起看看吧。
    2016-12-12
  • SpringBoot集成內(nèi)存數(shù)據(jù)庫hsqldb的實(shí)踐

    SpringBoot集成內(nèi)存數(shù)據(jù)庫hsqldb的實(shí)踐

    hsqldb只需要添加對應(yīng)的依賴,然后在配置文件進(jìn)行配置。不需要安裝一個(gè)數(shù)據(jù)庫,本文就來介紹一下具體使用,感興趣的可以了解一下
    2021-09-09
  • 淺析SpringBoot實(shí)現(xiàn)防盜鏈的五大常見漏洞和解決方法

    淺析SpringBoot實(shí)現(xiàn)防盜鏈的五大常見漏洞和解決方法

    文章詳細(xì)分析了Spring?Boot防盜鏈的五大致命漏洞,包括僅依賴Referer校驗(yàn),未處理CDN代理穿透問題,不使用動(dòng)態(tài)Token驗(yàn)證和未實(shí)現(xiàn)流量監(jiān)控與異常處理,每個(gè)漏洞都提供了代碼示例,并給出了解決方案
    2026-05-05
  • SpringBoot?JavaMailSender發(fā)送郵件功能(實(shí)例詳解)

    SpringBoot?JavaMailSender發(fā)送郵件功能(實(shí)例詳解)

    JavaMailSender是Spring提供的,非常好用的,實(shí)現(xiàn)郵件發(fā)送的接口 ,這篇文章主要介紹了SpringBoot?JavaMailSender發(fā)送郵件功能,需要的朋友可以參考下
    2024-03-03
  • 詳解Java注解知識點(diǎn)

    詳解Java注解知識點(diǎn)

    這篇文章主要介紹了詳解Java注解知識點(diǎn),文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-05-05
  • IDEA 包轉(zhuǎn)模塊的解決步驟

    IDEA 包轉(zhuǎn)模塊的解決步驟

    很多朋友遇到這樣一個(gè)問題,直接在idea拉取代碼,發(fā)現(xiàn)創(chuàng)建的模塊包類型不一樣了,類似這樣的問題該如何處理呢?很多朋友向小編求助,在這統(tǒng)一回答大家,需要的朋友參考下本文吧
    2021-06-06
  • SpringBoot優(yōu)化啟動(dòng)速度實(shí)現(xiàn)過程

    SpringBoot優(yōu)化啟動(dòng)速度實(shí)現(xiàn)過程

    本文主要介紹了SpringBoot啟動(dòng)慢的原因,并提供了多種針對性優(yōu)化方案,如延遲Bean初始化、關(guān)閉JMX、減少組件掃描、升級JDK及SpringBoot版本等,旨在提升應(yīng)用啟動(dòng)速度
    2026-05-05

最新評論

沛县| 高雄市| 金门县| 常德市| 吴旗县| 济宁市| 永济市| 樟树市| 濮阳县| 枞阳县| 邹城市| 确山县| 余干县| 新昌县| 建昌县| 左云县| 库尔勒市| 顺义区| 汪清县| 游戏| 尼勒克县| 贞丰县| 长宁县| 枣阳市| 塔河县| 大宁县| 岐山县| 内黄县| 赞皇县| 新田县| 沽源县| 会东县| 巴彦淖尔市| 广昌县| 工布江达县| 铜川市| 乡宁县| 上栗县| 黄大仙区| 苍南县| 景洪市|