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

一次學(xué)會(huì)JWT之Java登錄、驗(yàn)證與權(quán)限控制完整流程

 更新時(shí)間:2025年09月22日 10:15:35   作者:YangQ27  
JWT(JSON Web Token)是一種開(kāi)放標(biāo)準(zhǔn)(RFC 7519),用于在網(wǎng)絡(luò)應(yīng)用環(huán)境間以緊湊的方式安全地傳遞信息,這篇文章主要介紹了JWT Java登錄、驗(yàn)證與權(quán)限控制的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下

1. JWT 基礎(chǔ)概念

1.1 什么是 JWT?

JWT(JSON Web Token)是一種基于 JSON 的輕量級(jí)認(rèn)證方式,用于在各方之間安全地傳遞信息。它常用于 前后端分離項(xiàng)目的登錄認(rèn)證,替代傳統(tǒng)的 Session 機(jī)制。

特點(diǎn):數(shù)據(jù)量小,傳輸快(輕量)、本身攜帶用戶信息,不依賴服務(wù)端存儲(chǔ)(自包含)、簽名保證數(shù)據(jù)完整性與可信度(簽名防篡改)。

1.2 為什么要用 JWT?

傳統(tǒng)的登錄認(rèn)證方式使用 Session 保存用戶信息,但在 前后端分離 項(xiàng)目中:

  • Session 需要服務(wù)端存儲(chǔ),會(huì)增加服務(wù)器壓力

  • 多臺(tái)服務(wù)器要共享 Session,需要引入 Redis

  • 移動(dòng)端、小程序調(diào)用不方便

JWT(JSON Web Token)

  • 無(wú)需服務(wù)端保存狀態(tài),無(wú)狀態(tài)認(rèn)證

  • Token 自包含用戶信息

  • 輕量、安全、跨平臺(tái)

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

JWT 一般由三部分組成,用 . 分隔:

Header.Payload.Signature

Header(頭部)

聲明簽名算法和類型,例如:

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

alg: 使用的簽名算法,如 HS256(HMAC SHA-256)、RS256(RSA SHA-256)等。

typ: 類型,固定為 JWT。

Payload(載荷)

存放實(shí)際信息(Claims),分為:

  • Registered claims(注冊(cè)字段):如 iss(簽發(fā)者)、exp(過(guò)期時(shí)間)等

  • Public claims(公共字段):自定義但公開(kāi)的字段

  • Private claims(私有字段):自定義且內(nèi)部使用

常用的字段(大家約定俗稱的字段,表示一些通用的信息)

字段含義示例
sub用戶唯一標(biāo)識(shí)(Subject)"sub": "user_10086"
exp過(guò)期時(shí)間(Expiration)"exp": 1723545600(時(shí)間戳)
iat簽發(fā)時(shí)間(Issued At)"iat": 1723459200
iss簽發(fā)者(Issuer)"iss": "myapp.com"

? 提醒:exp 最常用,用來(lái)控制 token 的有效期。

{
  "sub": "user123",
  "exp": 1723545600,
  "iss": "Yq",
  "iat": 1723459200,
}

自定義信息(這部分是你自己決定要告訴別人的信息)

{
  "name": "Yang",
  "role": "管理員",
  "email": "YangQ@example.com"
}

?? 注意:Payload 是 Base64 編碼的,不是加密的! 所以不要在其中存放敏感信息(如密碼)。

Signature(簽名)

用密鑰和前兩部分生成的簽名,防止數(shù)據(jù)被篡改。如(使用HMAC SHA256):

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

2. JWT 的工作流程

  1. 用戶登錄 → 服務(wù)器驗(yàn)證身份

  2. 服務(wù)器生成 JWT 并返回給客戶端

  3. 客戶端每次請(qǐng)求都帶上 JWT(通常放在 HTTP Header 中 Authorization: Bearer <token>

  4. 服務(wù)器驗(yàn)證 JWT 的合法性 → 允許訪問(wèn)資源

優(yōu)點(diǎn):無(wú)狀態(tài)、輕量、跨域支持

缺點(diǎn):無(wú)法輕易撤銷(需維護(hù)黑名單)

3. Java中操作JWT

Java 生態(tài)中最流行的 JWT 庫(kù)是 jjwt,由 Apache 提供,簡(jiǎn)單易用。

3.1 我們先創(chuàng)建 Spring Boot 項(xiàng)目并引入依賴

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- JWT -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.5</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.11.5</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId>
        <version>0.11.5</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>

3.2 再封裝一個(gè)JwtUtil工具類,用于生成和驗(yàn)證 Token。

package com.yg.jwt.util;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Date;

public class JwtUtil {
    // 建議從配置文件讀取
    private static final Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    private static final long EXPIRATION = 60 * 1000; // 1分鐘

    // 生成 Token
    public static String generateToken(String username, String role) {
        return Jwts.builder()
                .setSubject(username)
                .claim("role", role)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
                .signWith(key)
                .compact();
    }

    // 解析 Token
    public static Claims parseToken(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }
}

3.3 實(shí)現(xiàn)登錄接口

package com.yg.jwt.controller;

import org.springframework.web.bind.annotation.*;
import com.yg.jwt.util.JwtUtil;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/auth")
public class AuthController {

    @PostMapping("/login")
    public Map<String, Object> login(@RequestParam String username, @RequestParam String password) {
        Map<String, Object> result = new HashMap<>();

        // 模擬賬號(hào)密碼驗(yàn)證
        if ("admin".equals(username) && "123456".equals(password)) {
            String token = JwtUtil.generateToken(username, "admin");
            result.put("code", 200);
            result.put("message", "登錄成功");
            result.put("token", token);
        } else {
            result.put("code", 401);
            result.put("message", "用戶名或密碼錯(cuò)誤");
        }
        return result;
    }
}

3.4 創(chuàng)建一個(gè)攔截器(JwtInterceptor.java)

攔截請(qǐng)求,用來(lái)驗(yàn)證 Token 是否有效。

package com.yg.jwt.interceptor;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import com.yg.jwt.util.JwtUtil;


@Component
public class JwtInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String authHeader = request.getHeader("Authorization");

        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String token = authHeader.substring(7);

            try {
                Claims claims = JwtUtil.parseToken(token);
                request.setAttribute("username", claims.getSubject());
                request.setAttribute("role", claims.get("role"));
                return true;
            } catch (ExpiredJwtException e) {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.getWriter().write("Token 已過(guò)期");
                return false;
            } catch (Exception e) {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.getWriter().write("無(wú)效 Token");
                return false;
            }
        }
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getWriter().write("缺少 Token");
        return false;
    }
}

3.5 配置攔截器

package com.yg.jwt.config;

import com.yg.jwt.interceptor.JwtInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private JwtInterceptor jwtInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/auth/login"); // 登錄接口放行
    }
}

?? 小插曲:為什么要配置攔截器?

因?yàn)镸VC 框架需要知道“有哪些攔截器要工作”(注冊(cè)機(jī)制)、統(tǒng)一處理(避免在每個(gè) Controller 里重復(fù)寫(xiě)驗(yàn)證邏輯)、全局控制(可以精確控制攔截哪些路徑、放行哪些路徑)、流程集成(攔截器是 MVC 生命周期的一部分,必須接入流程)

3.6 編寫(xiě)受保護(hù)接口

package com.yg.jwt.controller;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/info")
    public String getUserInfo(@RequestAttribute("username") String username,
                              @RequestAttribute("role") String role) {
        return "當(dāng)前用戶:" + username + ",角色:" + role;
    }
}

3.7 項(xiàng)目結(jié)構(gòu)圖

jwt
│── pom.xml                # Maven 依賴
│── src
│   ├── main
│   │   ├── java
│   │   │   └── com.yq.jwt
│   │   │       ├── config
│   │   │       │    └── WebConfig.java          # 配置攔截器
│   │   │       ├── controller
│   │   │       │    ├── AuthController.java     # 登錄接口
│   │   │       │    └── UserController.java     # 受保護(hù)接口
│   │   │       ├── interceptor
│   │   │       │    └── JwtInterceptor.java     # JWT 攔截器
│   │   │       └── util
│   │   │            └── JwtUtil.java            # JWT 工具類
│   │   └── resources
│   │        └── application.yml                 # 配置文件
│   └── test                                     
│        └── java                                 # 測(cè)試代碼

4. 測(cè)試流程

本篇章用的測(cè)試工具為Apifox,使用其他測(cè)試工具也是可以的(如:Postman)。

4.1 登錄獲取 Token

POST http://localhost:8080/auth/login
參數(shù):
username=admin
password=123456

返回:

4.2 訪問(wèn)受保護(hù)接口

GET http://localhost:8080/user/info
Header:
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

把剛剛從后端返回回來(lái)的token放到Headers里面,接著訪問(wèn)后端請(qǐng)求數(shù)據(jù)

5. 總結(jié)

JWT 是一種輕量、跨域、無(wú)狀態(tài)的認(rèn)證方式,非常適合現(xiàn)代 Web 和微服務(wù)架構(gòu)。通過(guò) Java 的 jjwt 庫(kù),我們可以快速生成、解析和驗(yàn)證 JWT,實(shí)現(xiàn)安全的身份驗(yàn)證機(jī)制。

到此這篇關(guān)于一次學(xué)會(huì)JWT之Java登錄、驗(yàn)證與權(quán)限控制完整流程的文章就介紹到這了,更多相關(guān)Java登錄、驗(yàn)證與權(quán)限控制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis自定義typeHandle過(guò)程解析

    Mybatis自定義typeHandle過(guò)程解析

    這篇文章主要介紹了Mybatis自定義typeHandle過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • java截取網(wǎng)頁(yè)圖片的方法

    java截取網(wǎng)頁(yè)圖片的方法

    這篇文章主要介紹了java截取網(wǎng)頁(yè)圖片的方法,涉及java調(diào)用第三方控件實(shí)現(xiàn)截圖的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • MyEclipse如何將項(xiàng)目的開(kāi)發(fā)環(huán)境與服務(wù)器的JDK 版本保持一致

    MyEclipse如何將項(xiàng)目的開(kāi)發(fā)環(huán)境與服務(wù)器的JDK 版本保持一致

    我們使用MyEclipse開(kāi)發(fā)Java項(xiàng)目開(kāi)發(fā)中,偶爾會(huì)遇到因項(xiàng)目開(kāi)發(fā)環(huán)境不協(xié)調(diào),導(dǎo)致這樣那樣的問(wèn)題,在這里以把所有環(huán)境調(diào)整為JDK1.6 為例,給大家詳細(xì)介紹MyEclipse如何將項(xiàng)目的開(kāi)發(fā)環(huán)境與服務(wù)器的JDK 版本保持一致,需要的朋友參考下吧
    2024-04-04
  • java中l(wèi)ong(Long)與int(Integer)之間的轉(zhuǎn)換方式

    java中l(wèi)ong(Long)與int(Integer)之間的轉(zhuǎn)換方式

    這篇文章主要介紹了java中l(wèi)ong(Long)與int(Integer)之間的轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • Mybatis-Plus樂(lè)觀鎖配置流程

    Mybatis-Plus樂(lè)觀鎖配置流程

    這篇文章主要介紹了Mybatis-Plus樂(lè)觀鎖配置使用流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作有一定的參考學(xué)習(xí)價(jià)值,感興趣的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2024-01-01
  • spring security自定義登錄頁(yè)面

    spring security自定義登錄頁(yè)面

    在項(xiàng)目中我們肯定不能使用Spring自己生成的登錄頁(yè)面,而要用我們自己的登錄頁(yè)面,下面通過(guò)本文給大家分享spring security自定義登錄頁(yè)面的實(shí)現(xiàn)方法,一起看看吧
    2017-09-09
  • SpringBoot配置Profile實(shí)現(xiàn)多環(huán)境支持

    SpringBoot配置Profile實(shí)現(xiàn)多環(huán)境支持

    這篇文章主要介紹了SpringBoot配置Profile實(shí)現(xiàn)多環(huán)境支持操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Spring AI框架結(jié)合Sentinel實(shí)現(xiàn)限流功能

    Spring AI框架結(jié)合Sentinel實(shí)現(xiàn)限流功能

    這篇文章主要為大家詳細(xì)介紹了如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的使用Spring AI框架結(jié)合Sentinel限流的功能,場(chǎng)景是一個(gè)智能客服系統(tǒng),感興趣的小伙伴可以了解下
    2025-06-06
  • java8 集合求差集、并集、交集的實(shí)例

    java8 集合求差集、并集、交集的實(shí)例

    下面小編就為大家分享一篇java8 集合求差集、并集、交集的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • Java線程之線程同步synchronized和volatile詳解

    Java線程之線程同步synchronized和volatile詳解

    這篇文章主要介紹了Java線程之線程同步synchronized和volatile詳解,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11

最新評(píng)論

襄汾县| 高唐县| 固镇县| 龙口市| 望城县| 八宿县| 会昌县| 巴中市| 漾濞| 汝州市| 阿城市| 松桃| 福贡县| 乌审旗| 剑河县| 武乡县| 西乌珠穆沁旗| 东乡| 霍山县| 祁东县| 静乐县| 宁德市| 浑源县| 青海省| 定陶县| 武宁县| 江北区| 合山市| 德化县| 右玉县| 双牌县| 高阳县| 巴青县| 鞍山市| 兴文县| 朔州市| 台江县| 东城区| 萝北县| 休宁县| 黄石市|