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

Java實現(xiàn)JWT令牌的示例代碼

 更新時間:2025年09月25日 08:30:16   作者:一只游魚  
JWT是一種無狀態(tài)認證方案,用于前后端分離項目,后端生成包含用戶信息的token,前端保存并隨請求頭攜帶,后端通過驗證token簽名、有效期等確保安全,實現(xiàn)跨服務身份認證,感興趣的可以了解一下

一、簡介

JWT (JSON Web Token) 是一種 跨服務、跨語言的認證解決方案,常用于前后端分離項目(比如 Spring Boot + Vue)。
它的主要作用是:

  1. 身份認證
    • 用戶登錄成功后,后端生成一個 JWT 返回給前端。
    • 前端每次請求時帶上這個 JWT,后端根據(jù)它來確認“你是誰”。
  2. 無狀態(tài)認證(不依賴 session
    • 傳統(tǒng)的 session 登錄需要服務器保存狀態(tài),用戶多了容易占用大量內(nèi)存。
    • JWT 是 自包含的,不需要服務器保存用戶狀態(tài),后端只要驗證 token 就行。
  3. 安全傳遞信息
    • JWT 由三部分組成:Header.Payload.Signature。
    • Payload 里可以存儲用戶 ID、角色、過期時間等信息。
    • Signature 簽名部分保證 token 不會被篡改。

二、實現(xiàn)流程

  1. 用戶在 Vue 前端輸入用戶名、密碼 → 發(fā)送到 Spring Boot 登錄接口。
  2. Spring Boot 驗證賬號密碼成功后 → 生成 JWT → 返回給前端。
  3. Vue 將 JWT 保存(通常存在 localStorage 或 sessionStorage)。
  4. 前端每次請求后端 API 時,在請求頭 Authorization 里帶上:Authorization: Bearer <token>
  5. Spring Boot 攔截請求,驗證 JWT 是否有效:
    • 簽名是否正確?
    • 是否過期?
    • 是否被篡改?
    • 驗證通過才放行,否則返回 401(未認證)。

如圖:

三、實戰(zhàn)

這里我們用spring boot + vue 來演示,

在配置中:

# JWT
#密鑰 注意密鑰要夠長58位
jwt.secret=abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+
#過期時間
jwt.expiration= 3600000

創(chuàng)建工具類:

@Value("${jwt.secret}")
private String secret;
 
@Value("${jwt.expiration}")
private long expiration; // 例如 3600000 = 1小時
 
// 生成 token
public String generateToken(String username) {
    Date now = new Date();
    Date expiryDate = new Date(now.getTime() + expiration);
 
    return Jwts.builder()
            .setSubject(username)
            .setIssuedAt(now)
            .setExpiration(expiryDate)
            .signWith(Keys.hmacShaKeyFor(secret.getBytes()))
            .compact();
}
 
// 獲取用戶名
public String getUsernameFromToken(String token) {
    return Jwts.parserBuilder()
            .setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
            .build()
            .parseClaimsJws(token)
            .getBody()
            .getSubject();
}
 
// 驗證 token
public boolean validateToken(String token) {
    try {
        Jwts.parserBuilder()
                .setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
                .build()
                .parseClaimsJws(token);
        return true;
    } catch (JwtException | IllegalArgumentException e) {
        return false;
    }
}

創(chuàng)建SecurityConfig文件

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    String path = exchange.getRequest().getURI().getPath();
 
 
    // 1. 放行登錄注冊
    if (path.startsWith("/user/login") || path.startsWith("/user/register") || path.startsWith("/chat-stream")) {
        return chain.filter(exchange);
    }
    //如果沒有Authorization頭,返回401
   if (!exchange.getRequest().getHeaders().containsKey("Authorization")) {
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }
 
    // 2. 處理Authorization頭
    String authHeader = exchange.getRequest().getHeaders().getFirst("Authorization");
    if (!authHeader.startsWith("Bearer ")) {
        // 無有效Token,返回401
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }
 
    // 3. 解析Token
    String token = authHeader.substring(7);
    if (!jwtUtil.validateToken(token)) {
        // Token驗證失?。ㄟ^期、簽名錯誤等),返回401并打印日志
        System.out.println("JWT驗證失敗:Token無效或過期 - " + token);
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }
 
    // 4. Token有效,設置認證信息到安全上下文
    String username = jwtUtil.getUsernameFromToken(token);
    Authentication auth = new UsernamePasswordAuthenticationToken(
            username, null, Collections.emptyList() // 無權限,可根據(jù)需求添加
    );
 
    // 5. 傳遞認證信息并繼續(xù)執(zhí)行過濾鏈
    return chain.filter(exchange)
            .contextWrite(ReactiveSecurityContextHolder.withAuthentication(auth));
}

接著創(chuàng)建JwtFilter

@Autowired
private JwtUtil jwtUtil;
 
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    String path = exchange.getRequest().getURI().getPath();
 
 
    // 1. 放行登錄注冊
    if (path.startsWith("/user/login") || path.startsWith("/user/register") || path.startsWith("/chat-stream")) {
        return chain.filter(exchange);
    }
 
    // 2. 處理Authorization頭
    String authHeader = exchange.getRequest().getHeaders().getFirst("Authorization");
    if (!authHeader.startsWith("Bearer ")) {
        // 無有效Token,返回401
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }
 
    // 3. 解析Token
    String token = authHeader.substring(7);
    if (!jwtUtil.validateToken(token)) {
        // Token驗證失敗(過期、簽名錯誤等),返回401并打印日志
        System.out.println("JWT驗證失?。篢oken無效或過期 - " + token);
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }
 
    // 4. Token有效,設置認證信息到安全上下文
    String username = jwtUtil.getUsernameFromToken(token);
    Authentication auth = new UsernamePasswordAuthenticationToken(
            username, null, Collections.emptyList() // 無權限,可根據(jù)需求添加
    );
 
    // 5. 傳遞認證信息并繼續(xù)執(zhí)行過濾鏈
    return chain.filter(exchange)
            .contextWrite(ReactiveSecurityContextHolder.withAuthentication(auth));
}

在控制層中,我們就可以在登錄邏輯中創(chuàng)建、返回給密鑰了:

//生成token
String token = jwtUtil.generateToken(user.getUserName());
//封裝返回數(shù)據(jù)
HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("token", token);

在前端中,處理登錄請求,將登錄成功后后端返回的token保存到瀏覽器:

const onFinish = async (values) => {
  loading.value = true
  try {
    if (isLogin.value) {
 
      //加密數(shù)據(jù)
      const encrypted = Encrypt(JSON.stringify(values))
      // 實現(xiàn)登錄邏輯
      const response = await request.post('/user/login', { data: encrypted })
 
      //保存token
      localStorage.setItem("token", JSON.parse(response.data).data.token)
 
     
      alert("登錄成功")
 
 
      // 刷新頁面
      // window.location.reload()
    } else {
      //加密數(shù)據(jù)
      const encrypted = Encrypt(JSON.stringify(values))
      // 實現(xiàn)注冊邏輯
      const response = await request.post('/user/register', { data: encrypted })
      console.log('注冊:', values)
    }
  } catch (error) {
    console.error(error)
    alert("登錄失敗")
  } finally {
    loading.value = false
  }
}

創(chuàng)建request.Js,將保存到本地瀏覽器的token放到請求頭中:

import axios from "axios";
const request = axios.create({
  baseURL: "/api",
  timeout: 30000, // 修改為30秒
  responseType: "stream" // 流式響應
});
// 請求攔截器:自動攜帶 token
request.interceptors.request.use(
  (config) => {
  const token = localStorage.getItem("token");
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);
export default request;

發(fā)送請求:

// 刪除
const deleteChat = (id) => {
  Modal.confirm({
    title: '確認刪除',
    content: '確定要刪除此對話嗎?(對話歷史也將會全部刪除)',
    okText: '確認',
    cancelText: '取消',
    onOk() {
      // 調用后端接口刪除對話
      eventSource?.close();
      request.delete(`/chat/delete/${id}`)
        .then((response) => {
          if (response.data.code === "200") {  
            //顯示更新成功
            message.success('刪除成功');
            //刷新對話列表
            getChatList();
          } else {
            //顯示更新失敗
            message.error('刪除失敗');
          }
        })
        .catch(err => {
          message.error('刪除失敗');
          // console.error('刪除失敗:', err);
        });
    },
    onCancel() {
      console.log('取消刪除');
    },
  });
};

運行可以看到,登錄成功后后端成功返回token:

Token成功保存:

如果token國企或者錯誤:

再次請求會顯示401無權限報錯

到此這篇關于Java實現(xiàn)JWT令牌的示例代碼的文章就介紹到這了,更多相關Java JWT令牌內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 什么是RESTful?API,有什么作用

    什么是RESTful?API,有什么作用

    提到RESTful?API大家勢必或多或少聽說過,但是什么是RESTful?API??如何理解RESTful?API?呢?今天咱們就來聊聊這個RESTful?API
    2023-11-11
  • SpringCloud中NacosNamingService的作用詳解

    SpringCloud中NacosNamingService的作用詳解

    這篇文章主要介紹了SpringCloud中NacosNamingService的作用詳解,NacosNamingService類完成服務實例注冊,撤銷與獲取服務實例操作,NacosNamingService初始化采用單例模式,使用反射生成,需要的朋友可以參考下
    2023-11-11
  • SpringCloud服務接口調用OpenFeign及使用詳解

    SpringCloud服務接口調用OpenFeign及使用詳解

    這篇文章主要介紹了SpringCloud服務接口調用——OpenFeign,在學習Ribbon時,服務間調用使用的是RestTemplate+Ribbon實現(xiàn),而Feign在此基礎上繼續(xù)進行了封裝,使服務間調用變得更加方便,需要的朋友可以參考下
    2023-04-04
  • 關于Spring項目對JDBC的支持與基本使用詳解

    關于Spring項目對JDBC的支持與基本使用詳解

    這段時間一直在觀看Spring框架,所以下面這篇文章主要給大家介紹了關于Spring項目對JDBC的支持與基本使用的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-11-11
  • Java NIO寫大文件對比(win7和mac)

    Java NIO寫大文件對比(win7和mac)

    這篇文章主要介紹了Java NIO寫大文件對比(win7和mac),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • mybatis的if判斷integer問題

    mybatis的if判斷integer問題

    這篇文章主要介紹了mybatis的if判斷integer問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java開發(fā)支付寶PC支付完整版

    Java開發(fā)支付寶PC支付完整版

    這篇文章主要介紹了Java開發(fā)支付寶PC支付完整版,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • Java如何獲取resources下的文件路徑和創(chuàng)建臨時文件

    Java如何獲取resources下的文件路徑和創(chuàng)建臨時文件

    這篇文章主要介紹了Java如何獲取resources下的文件路徑和創(chuàng)建臨時文件,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 最新評論