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

SpringBoot實(shí)現(xiàn)JWT認(rèn)證的完整方案

 更新時(shí)間:2025年10月23日 08:22:58   作者:匆匆忙忙游刃有余  
JWT(JSON?Web?Token)是一種用于在網(wǎng)絡(luò)應(yīng)用間安全傳遞信息的開放標(biāo)準(zhǔn),特別適合分布式系統(tǒng)的身份驗(yàn)證,下面我將詳細(xì)介紹如何在SpringBoot項(xiàng)目中實(shí)現(xiàn)JWT認(rèn)證的完整方案,需要的朋友可以參考下

引言

JWT(JSON Web Token)是一種用于在網(wǎng)絡(luò)應(yīng)用間安全傳遞信息的開放標(biāo)準(zhǔn),特別適合分布式系統(tǒng)的身份驗(yàn)證。下面我將詳細(xì)介紹如何在SpringBoot項(xiàng)目中實(shí)現(xiàn)JWT認(rèn)證。

一、JWT 基礎(chǔ)概念

JWT由三部分組成,用.連接:

  1. Header(頭部):包含令牌類型和使用的加密算法
  2. Payload(載荷):包含用戶信息和聲明
  3. Signature(簽名):使用密鑰對前兩部分進(jìn)行簽名,確保信息不被篡改

二、項(xiàng)目準(zhǔn)備

1. 添加依賴

pom.xml中添加JWT相關(guān)依賴:

<!-- JWT依賴 -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.19.2</version>
</dependency>
<!-- Spring Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Lombok(可選,用于簡化代碼) -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

2. 配置文件

application.yml中添加JWT相關(guān)配置:

spring:
  application:
    name: springboot-jwt-demo

jwt:
  # 密鑰
  secret: your-secret-key-change-in-production
  # 過期時(shí)間(毫秒)
  expire-time: 86400000
  # 請求頭中Token的名稱
  header: Authorization
  # Token前綴
  token-prefix: Bearer

三、核心代碼實(shí)現(xiàn)

1. JWT工具類

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Map;

@Component
public class JWTUtil {
    
    @Value("${jwt.secret}")
    private String secret;
    
    @Value("${jwt.expire-time}")
    private long expireTime;
    
    /**
     * 生成Token
     * @param claims 要存儲在Token中的信息
     * @return 生成的Token字符串
     */
    public String generateToken(Map<String, String> claims) {
        // 設(shè)置過期時(shí)間
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.MILLISECOND, (int) expireTime);
        
        // 創(chuàng)建JWT Builder
        JWTCreator.Builder builder = JWT.create();
        
        // 添加載荷
        claims.forEach(builder::withClaim);
        
        // 設(shè)置簽名和過期時(shí)間,生成Token
        return builder.withExpiresAt(instance.getTime())
                .sign(Algorithm.HMAC256(secret));
    }
    
    /**
     * 驗(yàn)證Token
     * @param token 要驗(yàn)證的Token
     * @return 驗(yàn)證后的DecodedJWT對象
     * @throws JWTVerificationException 驗(yàn)證失敗時(shí)拋出異常
     */
    public DecodedJWT verifyToken(String token) {
        return JWT.require(Algorithm.HMAC256(secret))
                .build()
                .verify(token);
    }
    
    /**
     * 解析Token
     * @param token 要解析的Token
     * @return 解析后的DecodedJWT對象
     */
    public DecodedJWT parseToken(String token) {
        return JWT.decode(token);
    }
    
    /**
     * 從Token中獲取指定的Claim
     * @param token Token字符串
     * @param claimName Claim名稱
     * @return Claim值
     */
    public String getClaim(String token, String claimName) {
        DecodedJWT decodedJWT = parseToken(token);
        return decodedJWT.getClaim(claimName).asString();
    }
}

2. JWT攔截器

import com.auth0.jwt.exceptions.JWTVerificationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

@Component
@Slf4j
public class JWTInterceptor implements HandlerInterceptor {
    
    @Autowired
    private JWTUtil jwtUtil;
    
    @Value("${jwt.header}")
    private String jwtHeader;
    
    @Value("${jwt.token-prefix}")
    private String tokenPrefix;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String token = request.getHeader(jwtHeader);
        
        // 檢查請求頭中是否包含Token
        if (token == null || "".equals(token.trim())) {
            response401(response, "Token不存在");
            return false;
        }
        
        // 移除Token前綴
        if (token.startsWith(tokenPrefix)) {
            token = token.replace(tokenPrefix, "").trim();
        } else {
            response401(response, "Token格式錯(cuò)誤");
            return false;
        }
        
        try {
            // 驗(yàn)證Token
            jwtUtil.verifyToken(token);
            log.info("Token驗(yàn)證成功");
            return true;
        } catch (JWTVerificationException e) {
            log.error("Token驗(yàn)證失敗: {}", e.getMessage());
            response401(response, "Token無效或已過期");
            return false;
        }
    }
    
    /**
     * 返回401錯(cuò)誤響應(yīng)
     */
    private void response401(HttpServletResponse response, String message) {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        
        try (PrintWriter out = response.getWriter()) {
            out.append("{\"code\": 401, \"message\": \"").append(message).append("\"}");
        } catch (Exception e) {
            log.error("響應(yīng)錯(cuò)誤: {}", e.getMessage());
        }
    }
}

3. 攔截器配置

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 InterceptorConfig implements WebMvcConfigurer {
    
    @Autowired
    private JWTInterceptor jwtInterceptor;
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加攔截器,攔截需要認(rèn)證的路徑
        registry.addInterceptor(jwtInterceptor)
                // 需要攔截的路徑
                .addPathPatterns("/api/**")
                // 排除不需要攔截的路徑
                .excludePathPatterns("/api/login", "/api/register", "/error");
    }
}

4. 實(shí)體類

import lombok.Data;

@Data
public class LoginRequest {
    private String username;
    private String password;
}

@Data
public class LoginResponse {
    private String token;
    private String username;
    private String message;
}

5. 用戶服務(wù)接口

public interface UserService {
    boolean login(String username, String password);
    boolean register(String username, String password);
}

6. 用戶服務(wù)實(shí)現(xiàn)

import org.springframework.stereotype.Service;

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

@Service
public class UserServiceImpl implements UserService {
    
    // 模擬數(shù)據(jù)庫,實(shí)際項(xiàng)目中應(yīng)使用數(shù)據(jù)庫存儲
    private final Map<String, String> userMap = new HashMap<>();
    
    public UserServiceImpl() {
        // 初始化測試用戶
        userMap.put("admin", "123456");
    }
    
    @Override
    public boolean login(String username, String password) {
        return userMap.containsKey(username) && userMap.get(username).equals(password);
    }
    
    @Override
    public boolean register(String username, String password) {
        if (userMap.containsKey(username)) {
            return false; // 用戶名已存在
        }
        userMap.put(username, password);
        return true;
    }
}

7. 登錄控制器

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

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

@RestController
@RequestMapping("/api")
public class AuthController {
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private JWTUtil jwtUtil;
    
    @Value("${jwt.token-prefix}")
    private String tokenPrefix;
    
    /**
     * 用戶登錄
     */
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest request) {
        if (userService.login(request.getUsername(), request.getPassword())) {
            // 構(gòu)建Token中的載荷信息
            Map<String, String> claims = new HashMap<>();
            claims.put("username", request.getUsername());
            
            // 生成Token
            String token = jwtUtil.generateToken(claims);
            
            // 構(gòu)建響應(yīng)
            LoginResponse response = new LoginResponse();
            response.setToken(tokenPrefix + " " + token);
            response.setUsername(request.getUsername());
            response.setMessage("登錄成功");
            
            return ResponseEntity.ok(response);
        }
        return ResponseEntity.badRequest().body("用戶名或密碼錯(cuò)誤");
    }
    
    /**
     * 用戶注冊
     */
    @PostMapping("/register")
    public ResponseEntity<?> register(@RequestBody LoginRequest request) {
        if (userService.register(request.getUsername(), request.getPassword())) {
            return ResponseEntity.ok("注冊成功");
        }
        return ResponseEntity.badRequest().body("用戶名已存在");
    }
    
    /**
     * 測試接口,需要驗(yàn)證Token
     */
    @GetMapping("/test")
    public ResponseEntity<?> test() {
        return ResponseEntity.ok("訪問成功,Token有效");
    }
}

四、安全性考慮

  1. 密鑰安全:密鑰必須保密,生產(chǎn)環(huán)境應(yīng)使用強(qiáng)密鑰
  2. Token過期時(shí)間:設(shè)置合理的過期時(shí)間,避免永久有效
  3. HTTPS傳輸:在生產(chǎn)環(huán)境中使用HTTPS傳輸Token
  4. 防XSS攻擊:Token存儲在localStorage時(shí)可能被XSS攻擊竊取
  5. Token刷新機(jī)制:實(shí)現(xiàn)Token刷新機(jī)制,避免頻繁登錄
  6. 黑名單機(jī)制:對于已注銷的Token,添加到黑名單中

五、優(yōu)化建議

  1. 使用Redis存儲Token:可以更靈活地管理Token生命周期
  2. 實(shí)現(xiàn)Refresh Token:提供長期的Refresh Token用于獲取新的Access Token
  3. 增加角色權(quán)限:在Token中添加用戶角色信息,實(shí)現(xiàn)更細(xì)粒度的權(quán)限控制
  4. 使用非對稱加密:生產(chǎn)環(huán)境可考慮使用RSA等非對稱加密算法
  5. 添加IP綁定:在Token中綁定用戶IP,增加安全性
  6. 添加日志記錄:記錄Token的生成、驗(yàn)證和使用情況

六、測試方法

  1. 啟動(dòng)SpringBoot應(yīng)用
  2. 使用Postman或其他工具測試登錄接口:POST http://localhost:8080/api/login
  3. 在請求體中添加用戶名和密碼
  4. 成功后將返回的Token添加到請求頭
  5. 訪問需要認(rèn)證的接口:GET http://localhost:8080/api/test

這個(gè)實(shí)現(xiàn)提供了SpringBoot中JWT認(rèn)證的完整流程,包括Token生成、驗(yàn)證和攔截器實(shí)現(xiàn)。您可以根據(jù)實(shí)際需求進(jìn)行調(diào)整和擴(kuò)展。

以上就是SpringBoot實(shí)現(xiàn)JWT認(rèn)證的完整方案的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot JWT認(rèn)證的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java調(diào)用接口返回亂碼問題及解決

    java調(diào)用接口返回亂碼問題及解決

    這篇文章主要介紹了java調(diào)用接口返回亂碼問題及解決,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • springboot 打包 failed with MalformedInputException: Input length=1

    springboot 打包 failed with MalformedInput

    本文主要介紹了SpringBoot項(xiàng)目在打包時(shí)常見的錯(cuò)誤,通常是由于資源文件的編碼問題導(dǎo)致的,下面就一起來介紹一下該問題的詳細(xì)步驟,感興趣的可以了解一下
    2025-07-07
  • Springboot如何通過自定義工具類獲取bean

    Springboot如何通過自定義工具類獲取bean

    這篇文章主要介紹了Springboot通過自定義工具類獲取bean方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 詳解Spring框架之基于Restful風(fēng)格實(shí)現(xiàn)的SpringMVC

    詳解Spring框架之基于Restful風(fēng)格實(shí)現(xiàn)的SpringMVC

    這篇文章主要介紹了詳解Spring框架之基于Restful風(fēng)格實(shí)現(xiàn)的SpringMVC,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Spring與Spring boot的區(qū)別介紹

    Spring與Spring boot的區(qū)別介紹

    Spring Boot框架的核心就是自動(dòng)配置,只要存在相應(yīng)的jar包,Spring就幫我們自動(dòng)配置。接下來通過本文給大家介紹Spring與Spring boot的區(qū)別介紹,非常不錯(cuò),需要的朋友參考下吧
    2017-04-04
  • Java中的這些騷操作你不能不知道!!!

    Java中的這些騷操作你不能不知道!!!

    今天在看python相關(guān)的東西,看到各種騷操作,回頭想了下Java有沒有什么騷操作,整理下面幾種,一起看一下吧,希望能給你帶來幫助
    2021-07-07
  • Java中File類方法詳解以及實(shí)踐

    Java中File類方法詳解以及實(shí)踐

    Java File類的功能非常強(qiáng)大,利用java基本上可以對文件進(jìn)行所有操作,下面這篇文章主要給大家介紹了關(guān)于Java中File類方法以及實(shí)踐的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • Java線程間共享實(shí)現(xiàn)方法詳解

    Java線程間共享實(shí)現(xiàn)方法詳解

    這篇文章主要介紹了Java線程間共享實(shí)現(xiàn)方法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • maven搭建java ee項(xiàng)目圖文教程

    maven搭建java ee項(xiàng)目圖文教程

    這篇文章主要為大家詳細(xì)介紹了maven搭建java ee項(xiàng)目圖文教程,感興趣的小伙伴們可以參考一下
    2016-04-04
  • 如何通過RabbitMq實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù)詳解

    如何通過RabbitMq實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù)詳解

    工作中經(jīng)常會(huì)有定時(shí)任務(wù)的需求,常見的做法可以使用Timer、Quartz、Hangfire等組件,這次想嘗試下新的思路,使用RabbitMQ死信隊(duì)列的機(jī)制來實(shí)現(xiàn)定時(shí)任務(wù),下面這篇文章主要給大家介紹了關(guān)于如何通過RabbitMq實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù)的相關(guān)資料,需要的朋友可以參考下
    2022-01-01

最新評論

长海县| 东乡族自治县| 濮阳市| 蒙山县| 延川县| 兴和县| 新干县| 土默特左旗| 平原县| 德保县| 鄂托克前旗| 福海县| 晴隆县| 都江堰市| 柯坪县| 井冈山市| 日土县| 和顺县| 华宁县| 遵义市| 堆龙德庆县| 定州市| 金川县| 东乡族自治县| 开鲁县| 长春市| 南和县| 九寨沟县| 九寨沟县| 九龙县| 阿拉善盟| 阜新| 大姚县| 木兰县| 南城县| 上饶县| 柳河县| 阿克苏市| 江川县| 英吉沙县| 大化|