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

Spring Security中集成JWT的完整實戰(zhàn)指南

 更新時間:2026年05月17日 10:06:00   作者:身如柳絮隨風(fēng)揚  
本文深入探討了現(xiàn)代Web應(yīng)用中的認(rèn)證授權(quán)方案,對比分析了JWT、Session-Cookie、OAuth2/OIDC、SAML 2.0等主流方案的優(yōu)缺點及適用場景,感興趣的小伙伴可以了解下

在構(gòu)建現(xiàn)代 Web 應(yīng)用和微服務(wù)時,認(rèn)證與授權(quán)是繞不開的核心話題。JWT(JSON Web Token)憑借無狀態(tài)、跨域友好等特性成為業(yè)界寵兒,但并非唯一選擇。同時,很多人疑惑:Spring Security 中到底怎么和 JWT 一起使用?隨機(jī)數(shù)又在哪些安全場景中發(fā)揮作用? 本文將從替代方案對比、隨機(jī)數(shù)應(yīng)用、Spring Security + JWT 實戰(zhàn)三個方面,為你徹底理清這些面試高頻問題。

一、除了 JWT,你還用過哪些認(rèn)證/授權(quán)方案

在實際項目中,我根據(jù)場景還使用過以下方案:

方案原理適用場景優(yōu)點缺點
傳統(tǒng) Session-Cookie服務(wù)端存儲 Session,客戶端存儲 Cookie單體應(yīng)用、用戶量不大實現(xiàn)簡單,主動失效方便占用服務(wù)端內(nèi)存,橫向擴(kuò)展需共享 Session
OAuth2 / OIDC第三方授權(quán),頒發(fā) Access Token + Refresh Token允許用戶授權(quán)第三方應(yīng)用訪問資源(如“使用微信登錄”)標(biāo)準(zhǔn)協(xié)議,廣泛支持實現(xiàn)復(fù)雜,需要引入授權(quán)服務(wù)器
SAML 2.0基于 XML 的安全斷言標(biāo)記語言,通過 SSO 認(rèn)證企業(yè)級單點登錄(如 Microsoft ADFS)成熟的企業(yè)標(biāo)準(zhǔn)XML 臃腫,配置復(fù)雜
API Key客戶端攜帶固定 Key 調(diào)用 API內(nèi)部服務(wù)調(diào)用、簡單開放 API實現(xiàn)極簡易泄露,無有效期,無用戶身份
Basic AuthHTTP 頭攜帶 base64(user:pass)內(nèi)部測試、簡單對接HTTP 原生支持明文傳輸(必須配合 HTTPS),無法注銷

1.1 什么時候選擇 JWT

  • 分布式/微服務(wù)架構(gòu):無需共享存儲,自帶用戶信息。
  • 移動端/跨域:Cookie 限制少,頭字段通用。
  • 短期授權(quán):如 API 調(diào)用、單點登錄的臨時憑證。

1.2 項目中的真實選型

  • 內(nèi)部運維系統(tǒng):Session + Redis 共享存儲。
  • 開放平臺 API:API Key + Secret 簽名(防止重放)。
  • 用戶端 App + Web:JWT(無狀態(tài),便于水平擴(kuò)展)。
  • 企業(yè) SSO 接入:OAuth2SAML(對接公司統(tǒng)一認(rèn)證)。

二、隨機(jī)數(shù)在安全中的妙用(你一定用過?。?/h2>

隨機(jī)數(shù)并非僅僅“隨機(jī)生成一個數(shù)字”,在安全領(lǐng)域有廣泛且關(guān)鍵的用途:

應(yīng)用場景隨機(jī)數(shù)作用示例
密碼加鹽(Salt)為每個密碼生成唯一隨機(jī)數(shù),與密碼一起哈希,抵抗彩虹表攻擊hash(password + salt)
驗證碼隨機(jī)生成數(shù)字/字母,短期有效,防止暴力 破解短信驗證碼 123456
CSRF Token每個會話或每個請求生成隨機(jī) Token,防御跨站請求偽造Spring Security 默認(rèn)開啟 _csrf
重置密碼 Token用戶請求重置密碼時,生成不可猜測的隨機(jī) Token 發(fā)送至郵箱token = UUID.randomUUID()
會話 ID隨機(jī)生成會話標(biāo)識,難以偽造JSESSIONID
OAuth2 State 參數(shù)防止 CSRF 攻擊,隨機(jī)字符串與請求綁定state=abc123
API 簽名 Nonce一次性的隨機(jī)數(shù),防止請求重放攻擊微信支付 nonce_str
ID 生成器(雪花算法)隨機(jī)+時間+機(jī)器號,生成全局唯一 IDSnowflake ID

2.1 Java 中生成隨機(jī)數(shù)的正確姿勢

// 安全的隨機(jī)數(shù)(推薦)
SecureRandom secureRandom = new SecureRandom();
byte[] bytes = new byte[16];
secureRandom.nextBytes(bytes);
String token = Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
// UUID(部分隨機(jī),不應(yīng)用于高安全場景)
String uuid = UUID.randomUUID().toString();
// 生成指定位數(shù)的數(shù)字驗證碼
String code = String.valueOf(secureRandom.nextInt(900000) + 100000);

三、Spring Security 中如何使用 JWT?——完整實戰(zhàn)

Spring Security 本身不直接提供 JWT 支持,需要通過 過濾器 解析 JWT 并手動將認(rèn)證信息存入 SecurityContext。下面是標(biāo)準(zhǔn)做法。

3.1 整體架構(gòu)流程圖

3.2 關(guān)鍵組件與代碼實現(xiàn)

3.2.1 添加依賴(JJWT)

<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>

3.2.2 JwtTokenUtil(生成與解析)

@Component
public class JwtTokenUtil {
    @Value("${jwt.secret}")
    private String secret;
    @Value("${jwt.expiration}")
    private Long expiration;

    public String generateToken(String username) {
        return Jwts.builder()
            .setSubject(username)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + expiration))
            .signWith(SignatureAlgorithm.HS256, secret)
            .compact();
    }

    public String getUsernameFromToken(String token) {
        return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getSubject();
    }

    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            return false;
        }
    }
}

3.2.3 JwtAuthenticationFilter(繼承 OncePerRequestFilter)

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                    HttpServletResponse response, 
                                    FilterChain chain) throws IOException, ServletException {
        String token = extractToken(request);
        if (token != null && jwtTokenUtil.validateToken(token)) {
            String username = jwtTokenUtil.getUsernameFromToken(token);
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            UsernamePasswordAuthenticationToken authentication = 
                new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        chain.doFilter(request, response);
    }

    private String extractToken(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}

3.2.4 SecurityConfig 配置

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Autowired
    private JwtAuthenticationFilter jwtFilter;
    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
                .antMatchers("/login", "/register").permitAll()
                .anyRequest().authenticated()
            .and()
            .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService);
        provider.setPasswordEncoder(passwordEncoder());
        return new ProviderManager(provider);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

3.2.5 登錄接口(生成 JWT)

@RestController
public class AuthController {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest request) {
        try {
            authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
            );
            String token = jwtTokenUtil.generateToken(request.getUsername());
            return ResponseEntity.ok(new JwtResponse(token));
        } catch (BadCredentialsException e) {
            return ResponseEntity.status(401).body("用戶名或密碼錯誤");
        }
    }
}

3.3 Spring Security 在 JWT 中所起的作用

角色說明
AuthenticationManager負(fù)責(zé)驗證用戶名密碼
SecurityContextHolder存儲已認(rèn)證的用戶信息,供后續(xù)業(yè)務(wù)代碼使用(如 @PreAuthorize
過濾器鏈我們插入的 JwtAuthenticationFilterUsernamePasswordAuthenticationFilter 之前執(zhí)行
UserDetailsService加載用戶權(quán)限,用于生成 Authentication 對象

核心:Spring Security 負(fù)責(zé)管理認(rèn)證狀態(tài),JWT 只是傳遞憑證的一種形式。我們編寫的過濾器將 JWT 解析后轉(zhuǎn)換為 Spring Security 能識別的 Authentication 對象。

四、總結(jié)與面試回答模板

面試官問:除了 JWT 你還用過其他認(rèn)證方案嗎?隨機(jī)數(shù)用過沒?

參考回答

“用過。在傳統(tǒng)單體項目中我使用 Session + Redis 共享存儲;對接第三方登錄時使用 OAuth2;內(nèi)部服務(wù)間調(diào)用使用 API Key + 簽名。隨機(jī)數(shù)在安全方面應(yīng)用廣泛:比如用戶密碼的 鹽值、短信驗證碼、重置密碼的 Token、OAuth2 的 state 參數(shù) 以及防止重放攻擊的 Nonce。我們項目中用 SecureRandom 生成高強(qiáng)度的隨機(jī)數(shù),比 Random 更安全。”

面試官問:你在 JWT 哪兒使用過 Spring Security?

參考回答:“在 Spring Boot 項目中,我將 JWT 作為無狀態(tài)認(rèn)證方案集成到 Spring Security。具體做法是:

  1. 編寫 JwtAuthenticationFilter 繼承 OncePerRequestFilter,解析請求頭中的 JWT。
  2. 如果 JWT 有效,從中提取用戶名,調(diào)用 UserDetailsService 加載權(quán)限,構(gòu)造 UsernamePasswordAuthenticationToken 并存入 SecurityContextHolder。
  3. SecurityConfig 中禁用 Session,設(shè)置 SessionCreationPolicy.STATELESS,并將自定義過濾器加到 UsernamePasswordAuthenticationFilter 之前。
  4. 登錄接口使用 AuthenticationManager 校驗用戶名密碼,校驗通過后生成 JWT 返回。

Spring Security 在這里提供認(rèn)證管理權(quán)限控制的骨架,JWT 只是憑證載體。”

到此這篇關(guān)于Spring Security中集成JWT的完整實戰(zhàn)指南的文章就介紹到這了,更多相關(guān)Spring Security集成JWT內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java實現(xiàn)搜索功能代碼詳解

    Java實現(xiàn)搜索功能代碼詳解

    這篇文章主要介紹了Java實現(xiàn)搜索功能代碼詳解,實現(xiàn)思路小編給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2017-12-12
  • Spring Boot+Nginx實現(xiàn)大文件下載功能

    Spring Boot+Nginx實現(xiàn)大文件下載功能

    相信很多小伙伴,在日常開放中都會遇到大文件下載的情況,大文件下載方式也有很多,比如非常流行的分片下載、斷點下載;當(dāng)然也可以結(jié)合Nginx來實現(xiàn)大文件下載,在中小項目非常適合使用,這篇文章主要介紹了Spring Boot結(jié)合Nginx實現(xiàn)大文件下載,需要的朋友可以參考下
    2024-05-05
  • Spring.Net IOC依賴注入原理流程解析

    Spring.Net IOC依賴注入原理流程解析

    這篇文章主要介紹了Spring.Net IOC依賴注入原理流程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • 對SpringBoot項目Jar包進(jìn)行加密防止反編譯

    對SpringBoot項目Jar包進(jìn)行加密防止反編譯

    最近項目要求部署到其他公司的服務(wù)器上,但是又不想將源碼泄露出去,要求對正式環(huán)境的啟動包進(jìn)行安全性處理,防止客戶直接通過反編譯工具將代碼反編譯出來,本文介紹了如何對SpringBoot項目Jar包進(jìn)行加密防止反編譯,需要的朋友可以參考下
    2023-10-10
  • IDEA 插件 mapper和xml互相跳轉(zhuǎn)操作

    IDEA 插件 mapper和xml互相跳轉(zhuǎn)操作

    這篇文章主要介紹了IDEA 插件 mapper和xml互相跳轉(zhuǎn)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • IDEA生成項目后出現(xiàn)的iml和idea文件問題

    IDEA生成項目后出現(xiàn)的iml和idea文件問題

    這篇文章主要介紹了IDEA生成項目后出現(xiàn)的iml和idea文件問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Java 8 Stream Api 中的 map和 flatMap 操作方法

    Java 8 Stream Api 中的 map和 flatMap 操作方法

    Java 8提供了非常好用的 Stream API ,可以很方便的操作集合。今天通過這篇文章給大家分享Java 8 Stream Api 中的 map和 flatMap 操作方法,需要的朋友可以參考下
    2019-11-11
  • 基于Java SSM的健康管理小程序的實現(xiàn)

    基于Java SSM的健康管理小程序的實現(xiàn)

    本篇文章主要為大家分享了基于SSM健康管理小程序的設(shè)計與實現(xiàn)。感興趣的小伙伴可以了解一下
    2021-11-11
  • Java中數(shù)組與棧和堆之間的關(guān)系說明

    Java中數(shù)組與棧和堆之間的關(guān)系說明

    文章講解了Java數(shù)組的初始化方式、內(nèi)存存儲機(jī)制、引用傳遞特性及遍歷、排序、拷貝技巧,強(qiáng)調(diào)引用數(shù)據(jù)類型方法調(diào)用時形參可能修改實參,但需注意引用指向單一對象的特性
    2025-08-08
  • SpringBoot文件分片上傳的示例代碼

    SpringBoot文件分片上傳的示例代碼

    分片上傳在很多地方都可以使用的到,本文主要介紹了SpringBoot文件分片上傳的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12

最新評論

武强县| 潼关县| 门头沟区| 辽中县| 讷河市| 崇仁县| 玉环县| 石首市| 马边| 广水市| 南召县| 北川| 农安县| 双鸭山市| 神木县| 东山县| 吉首市| 博客| 烟台市| 桐城市| 大洼县| 彩票| 莎车县| 游戏| 莱州市| 通道| 尖扎县| 礼泉县| 宜君县| 威宁| 石棉县| 睢宁县| 南郑县| 广水市| 固原市| 云龙县| 临清市| 体育| 社旗县| 道真| 漳州市|