使用Spring Security和JWT實(shí)現(xiàn)安全認(rèn)證機(jī)制
引言
在現(xiàn)代 Web 應(yīng)用中,安全認(rèn)證和授權(quán)是保障數(shù)據(jù)安全和用戶隱私的核心機(jī)制。Spring Security 是 Spring 框架下專為安全設(shè)計(jì)的模塊,具有高度的可配置性和擴(kuò)展性。而 JWT(JSON Web Token) 則是當(dāng)前流行的認(rèn)證解決方案,因其無狀態(tài)、可擴(kuò)展性強(qiáng)等特點(diǎn)被廣泛應(yīng)用于微服務(wù)和移動(dòng)應(yīng)用中。
本文將從以下幾個(gè)部分詳細(xì)介紹如何使用 Spring Security 和 JWT 實(shí)現(xiàn)一個(gè)完整的認(rèn)證機(jī)制:
- JWT 認(rèn)證流程概述
- Spring Security 的基本配置
- JWT 生成與解析
- 基于 Spring Security 的 JWT 安全配置
- 實(shí)現(xiàn)用戶登錄和認(rèn)證
1. JWT 認(rèn)證流程概述
JWT 的認(rèn)證流程如下:
- 用戶登錄:用戶通過用戶名和密碼發(fā)送請(qǐng)求給服務(wù)器。
- 服務(wù)器驗(yàn)證:服務(wù)器驗(yàn)證用戶身份,驗(yàn)證通過后生成 JWT Token。
- Token 下發(fā):服務(wù)器將生成的 Token 返回給客戶端。
- 后續(xù)請(qǐng)求攜帶 Token:客戶端在后續(xù)請(qǐng)求中將 JWT Token 添加到請(qǐng)求頭中,服務(wù)器通過解析和驗(yàn)證 Token 確認(rèn)請(qǐng)求的合法性。
這種方式的核心優(yōu)勢(shì)在于 Token 是無狀態(tài)的,服務(wù)器無需維護(hù)用戶的會(huì)話信息,且 JWT 可在分布式系統(tǒng)中實(shí)現(xiàn)共享認(rèn)證。
2. Spring Security 的基本配置
創(chuàng)建一個(gè)簡(jiǎn)單的 Spring Boot 項(xiàng)目,并添加 Spring Security 和 JWT 的依賴:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
配置 SecurityConfig 類
創(chuàng)建 SecurityConfig 類以配置 Spring Security 基本設(shè)置:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated();
}
}
上面的配置指定 /login 接口公開訪問,其余接口需要認(rèn)證后才能訪問。
3. JWT 生成與解析
使用 JWT 庫(kù)生成和解析 Token。創(chuàng)建 JwtUtil 工具類,實(shí)現(xiàn)生成和驗(yàn)證 JWT 的方法:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtUtil {
private static final String SECRET_KEY = "mySecretKey";
// 生成 JWT
public static String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 86400000)) // 24小時(shí)有效期
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
// 解析 JWT
public static Claims parseToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
}
}
4. 基于 Spring Security 的 JWT 安全配置
在 Spring Security 過濾鏈中添加 JWT 過濾器。實(shí)現(xiàn)一個(gè) JwtAuthenticationFilter 類,在每次請(qǐng)求時(shí)攔截并驗(yàn)證 Token:
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import io.jsonwebtoken.Claims;
public class JwtAuthenticationFilter extends BasicAuthenticationFilter {
public JwtAuthenticationFilter(AuthenticationManager authManager) {
super(authManager);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
String token = request.getHeader("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
chain.doFilter(request, response);
return;
}
Claims claims = JwtUtil.parseToken(token.replace("Bearer ", ""));
String username = claims.getSubject();
if (username != null) {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
SecurityContextHolder.getContext().setAuthentication(auth);
}
chain.doFilter(request, response);
}
}
將 JwtAuthenticationFilter 過濾器添加到 SecurityConfig 中:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()));
}
5. 實(shí)現(xiàn)用戶登錄和認(rèn)證
創(chuàng)建一個(gè)登錄控制器 AuthController,驗(yàn)證用戶后生成 JWT:
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
@RestController
public class AuthController {
@PostMapping("/login")
public void login(@RequestParam String username, @RequestParam String password, HttpServletResponse response) {
// 這里簡(jiǎn)單校驗(yàn)用戶名密碼
if ("user".equals(username) && "password".equals(password)) {
String token = JwtUtil.generateToken(username);
response.setHeader("Authorization", "Bearer " + token);
} else {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
}
}
以上代碼實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的登錄接口,用戶登錄成功后將返回 JWT Token,并將該 Token 存儲(chǔ)在響應(yīng)頭中。
6. 測(cè)試與驗(yàn)證
- 獲取 Token:使用客戶端(例如 Postman)請(qǐng)求
/login接口,得到包含 JWT Token 的響應(yīng)頭。 - 訪問受保護(hù)接口:將 Token 添加到請(qǐng)求頭
Authorization中,再次請(qǐng)求受保護(hù)接口,驗(yàn)證是否可以成功訪問。
結(jié)論
通過以上步驟,我們實(shí)現(xiàn)了一個(gè)基于 Spring Security 和 JWT 的安全認(rèn)證系統(tǒng)。在實(shí)際項(xiàng)目中,可以進(jìn)一步擴(kuò)展此功能,例如集成數(shù)據(jù)庫(kù)實(shí)現(xiàn)用戶管理、配置 JWT 自動(dòng)續(xù)簽等。這種基于 JWT 的無狀態(tài)認(rèn)證適用于分布式系統(tǒng)和微服務(wù)架構(gòu),有助于提高系統(tǒng)的安全性和可擴(kuò)展性。
以上就是使用Spring Security和JWT實(shí)現(xiàn)安全認(rèn)證機(jī)制的詳細(xì)內(nèi)容,更多關(guān)于Spring Security JWT安全認(rèn)證的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java源碼解析之HashMap的put、resize方法詳解
這篇文章主要介紹了Java源碼解析之HashMap的put、resize方法詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很大的幫助,需要的朋友可以參考下2021-04-04
SpringBoot中讀取application.properties配置文件的方法
這篇文章主要介紹了SpringBoot中讀取application.properties配置文件的三種方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-02-02
Mybatis-Plus通過SQL注入器實(shí)現(xiàn)批量插入的實(shí)踐
本文主要介紹了Mybatis-Plus通過SQL注入器實(shí)現(xiàn)批量插入的實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
Java并發(fā)編程之CountDownLatch原理詳解
這篇文章主要介紹了Java并發(fā)編程之CountDownLatch原理詳解,CountDownLatch類中使用了一個(gè)繼承自AQS的共享鎖Sync對(duì)象,構(gòu)造CountDownLatch對(duì)象時(shí)會(huì)將傳入的線程數(shù)值設(shè)為AQS的state值,需要的朋友可以參考下2023-12-12
java中replaceAll替換圓括號(hào)實(shí)例代碼
正則表達(dá)式的保留字符主要有:圓括號(hào)、方括號(hào)、花括號(hào)、豎線、橫線、點(diǎn)號(hào)、加號(hào)、星號(hào)、反斜桿等等,下面這篇文章主要給大家介紹了關(guān)于java中replaceAll替換圓括號(hào)的相關(guān)資料,需要的朋友可以參考下2022-10-10
SpringBoot自動(dòng)裝配Import示例詳解
SpringBoot中@Import注解的使用可以幫助開發(fā)者將指定的Bean或配置類導(dǎo)入到IOC容器中,該注解支持四種用法:導(dǎo)入Bean、導(dǎo)入配置類、實(shí)現(xiàn)ImportSelector接口和實(shí)現(xiàn),感興趣的朋友一起看看吧2024-09-09
詳解java實(shí)現(xiàn)HTTP請(qǐng)求的三種方式
這篇文章主要介紹了java實(shí)現(xiàn)HTTP請(qǐng)求的三種方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
自己動(dòng)手在Spring-Boot上加強(qiáng)國(guó)際化功能的示例
這篇文章主要介紹了自己動(dòng)手在Spring-Boot上加強(qiáng)國(guó)際化功能的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04

