Spring?Boot基于?JWT?優(yōu)化?Spring?Security?無狀態(tài)登錄實戰(zhàn)指南
Spring Boot 實戰(zhàn):基于 JWT 優(yōu)化 Spring Security 無狀態(tài)登錄
在上一篇文章中,我們通過 Spring Security 實現(xiàn)了基礎的接口權限控制,但采用的 HTTP Basic 登錄存在明顯缺陷:安全性,用戶名和密碼只是簡單的通過 Base64 編碼之后就開始傳送了,很容易被破解,進而暴露用戶信息。
本文將引入 JWT(JSON Web Token) 技術,重構登錄流程,讓接口即安全又貼合企業(yè)級項目需求。
一、先搞懂:為什么需要 JWT?
Jwt的核心優(yōu)勢是 無狀態(tài):
- 登錄成功后,服務器生成一個包含用戶信息和權限的加密 Token,直接返回給客戶端;
- 客戶端后續(xù)請求時,只需在請求頭攜帶 Token,服務器無需存儲任何狀態(tài),直接通過 Token 驗證身份和權限;
- 多臺服務器共用一套 Token 驗證邏輯,無需同步狀態(tài),完美適配分布式部署。
二、準備工作:添加 JWT 依賴
在 pom.xml 的 <dependencies> 標簽中,新增 JWT 相關依賴(基于 JJWT 框架,Spring 官方推薦):
<!-- JWT 核心依賴(JJWT) -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<!-- JWT 實現(xiàn)依賴 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<!-- JWT 加密算法依賴 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>添加后點擊 IDEA 右上角的 “Load Maven Changes” 刷新依賴,確保無紅色報錯。
三、第一步:實現(xiàn) JWT 工具類(核心)
JWT 的核心操作包括 生成 Token、驗證 Token、解析 Token 中的用戶信息,我們創(chuàng)建一個工具類封裝這些邏輯,方便后續(xù)調用。
在 com.example.firstspringbootproject.utils 包下創(chuàng)建 JwtUtil 類:
package com.example.firstspringbootproject.utils;
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
@Component
public class JwtUtil {
// 1. 從配置文件讀取 JWT 關鍵參數(shù)(避免硬編碼)
@Value("${jwt.secret}") // 密鑰(必須保密,建議在生產環(huán)境用環(huán)境變量配置)
private String secret;
@Value("${jwt.expiration}") // Token 過期時間(單位:毫秒,這里配置 2 小時)
private long expiration;
@Value("${jwt.header}") // 請求頭中攜帶 Token 的字段名(如 Authorization)
private String tokenHeader;
@Value("${jwt.prefix}") // Token 前綴(如 Bearer,規(guī)范要求加空格)
private String tokenPrefix;
// 2. 生成 Token:基于用戶信息(用戶名、角色)
public String generateToken(UserDetails userDetails) {
// 存儲 Token 中的自定義信息(Payload)
Map<String, Object> claims = new HashMap<>();
// 將用戶角色存入 Token(后續(xù)驗證權限用)
claims.put("roles", userDetails.getAuthorities().stream()
.map(authority -> authority.getAuthority())
.toList());
// 構建 Token 并返回
return Jwts.builder()
.setClaims(claims) // 自定義信息
.setSubject(userDetails.getUsername()) // 用戶名(唯一標識)
.setIssuedAt(new Date()) // 簽發(fā)時間
.setExpiration(new Date(System.currentTimeMillis() + expiration)) // 過期時間
.signWith(SignatureAlgorithm.HS512, secret) // 加密算法(HS512)+ 密鑰
.compact();
}
// 3. 從 Token 中獲取用戶名
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
// 4. 驗證 Token 是否有效(未過期 + 用戶名匹配)
public boolean validateToken(String token, UserDetails userDetails) {
String username = getUsernameFromToken(token);
// 驗證邏輯:用戶名一致 + Token 未過期 + Token 未被篡改
return username.equals(userDetails.getUsername())
&& !isTokenExpired(token);
}
// 5. 從 Token 中獲取自定義角色信息
public String getRoleFromToken(String token) {
Claims claims = getAllClaimsFromToken(token);
// 從自定義信息中獲取角色列表(這里簡化為單個角色,多角色可返回 List)
return ((List<String>) claims.get("roles")).get(0);
}
// ------------------------------
// 以下是內部工具方法(無需外部調用)
// ------------------------------
// 解析 Token,獲取所有自定義信息(Payload)
private Claims getAllClaimsFromToken(String token) {
try {
return Jwts.parser()
.setSigningKey(secret) // 用密鑰解密
.parseClaimsJws(token)
.getBody();
} catch (ExpiredJwtException | MalformedJwtException | SignatureException
| IllegalArgumentException | UnsupportedJwtException e) {
// 捕獲 Token 異常(過期、格式錯誤、簽名錯誤等)
throw new RuntimeException("無效的 Token:" + e.getMessage());
}
}
// 從 Token 中獲取指定信息(通用方法)
private <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
// 判斷 Token 是否過期
private boolean isTokenExpired(String token) {
final Date expirationDate = getClaimFromToken(token, Claims::getExpiration);
return expirationDate.before(new Date());
}
// 6. 輔助方法:從請求頭中提取 Token(去除前綴)
public String extractTokenFromHeader(String header) {
if (header != null && header.startsWith(tokenPrefix)) {
// 例如:header = "Bearer eyJhbGciOiJIUzI1NiJ9...",返回后面的 Token 部分
return header.substring(tokenPrefix.length()).trim();
}
return null;
}
// Getter 方法(供外部獲取配置參數(shù))
public String getTokenHeader() {
return tokenHeader;
}
public String getTokenPrefix() {
return tokenPrefix;
}
}四、第二步:配置 JWT 參數(shù)(避免硬編碼)
在 src/main/resources/application.yml(或 application.properties)中,添加 JWT 相關配置(替換硬編碼,方便后續(xù)修改):
# JWT 配置 jwt: secret: firstspringbootproject2025secretkeyfirstspringbootproject2025secretkeyfirstspringbootproject2025secretkey # 密鑰(生產環(huán)境建議用 64 位以上隨機字符串) # expiration: 7200000 # Token 過期時間(7200000 毫秒 = 2 小時) expiration: 1000 # Token 過期時間(1000 毫秒 = 1 秒) header: Authorization # 請求頭字段名 prefix: Bearer # Token 前綴(注意末尾有空格)
五、第三步:實現(xiàn) JWT 登錄接口(替換 HTTP Basic)
HTTP Basic 登錄是通過瀏覽器彈窗輸入賬號密碼,體驗較差;我們需要自定義一個 登錄接口(如 /api/login),客戶端通過 JSON 提交賬號密碼,服務器驗證通過后返回 JWT Token。
1. 創(chuàng)建登錄請求參數(shù)實體類
在 com.example.firstspringbootproject.dto 包下創(chuàng)建 LoginRequestDTO(接收客戶端提交的賬號密碼):
package com.example.firstspringbootproject.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
@Schema(name = "LoginRequestDTO", description = "登錄請求參數(shù)")
public class LoginRequestDTO {
@NotBlank(message = "用戶名不能為空")
@Schema(description = "用戶名", example = "admin")
private String username;
@NotBlank(message = "密碼不能為空")
@Schema(description = "密碼", example = "123456")
private String password;
}2. 創(chuàng)建登錄控制器
在 com.example.firstspringbootproject.controller 包下創(chuàng)建 AuthController,實現(xiàn)登錄接口:
package com.example.firstspringbootproject.controller;
import com.example.firstspringbootproject.dto.LoginRequestDTO;
import com.example.firstspringbootproject.common.Result;
import com.example.firstspringbootproject.utils.JwtUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api")
@Tag(name = "認證接口", description = "登錄、Token 相關接口")
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager; // Spring Security 認證管理器
@Autowired
private JwtUtil jwtUtil; // 自定義 JWT 工具類
/**
* 登錄接口:接收賬號密碼,驗證通過后返回 JWT Token
*/
@PostMapping("/login")
@Operation(summary = "用戶登錄", description = "提交用戶名和密碼,獲取 JWT Token")
public Result<Map<String, String>> login(@Valid @RequestBody LoginRequestDTO loginRequest) {
// 1. 調用 Spring Security 認證管理器,驗證賬號密碼
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getUsername(),
loginRequest.getPassword()
)
);
// 2. 認證通過:從認證結果中獲取用戶信息
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
// 3. 生成 JWT Token
String token = jwtUtil.generateToken(userDetails);
// 4. 構建返回結果(包含 Token 和過期提示)
Map<String, String> resultMap = new HashMap<>();
resultMap.put("token", token);
resultMap.put("expiration", "Token 有效期 2 小時,請及時刷新");
resultMap.put("role", jwtUtil.getRoleFromToken(token)); // 返回用戶角色,方便前端處理
return Result.success(resultMap);
}
}六、第四步:實現(xiàn) JWT 認證過濾器(核心攔截邏輯)
客戶端登錄成功后,后續(xù)請求會在 Authorization 頭中攜帶 Token(格式:Bearer eyJhbGciOiJIUzI1NiJ9...)。我們需要自定義一個 過濾器,在請求到達接口前攔截 Token,完成以下操作:
- 從請求頭中提取 Token;
- 驗證 Token 有效性;
- 從 Token 中解析用戶信息和角色;
- 將用戶信息存入 Spring Security 上下文,讓后續(xù)權限校驗生效。
在 com.example.firstspringbootproject.filter 包下創(chuàng)建 JwtAuthenticationFilter 類:
package com.example.firstspringbootproject.filter;
import com.example.firstspringbootproject.utils.JwtUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
// 自定義 JWT 認證過濾器:每次請求都會執(zhí)行(OncePerRequestFilter 確保一次請求只執(zhí)行一次)
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;
@Autowired
private UserDetailsService userDetailsService; // 之前實現(xiàn)的用戶查詢服務
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain
) throws ServletException, IOException {
try {
// 1. 從請求頭中提取 Token
String token = jwtUtil.extractTokenFromHeader(
request.getHeader(jwtUtil.getTokenHeader())
);
// 2. 驗證 Token:非空 + 有效
if (token != null) {
// 2.1 從 Token 中獲取用戶名
String username = jwtUtil.getUsernameFromToken(token);
// 2.2 若用戶名存在,且 Spring Security 上下文未存儲用戶信息(未登錄)
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
// 2.3 從數(shù)據(jù)庫查詢用戶完整信息(UserDetails)
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// 2.4 驗證 Token 有效性(未過期 + 用戶名匹配)
if (jwtUtil.validateToken(token, userDetails)) {
// 3. 構建認證對象,存入 Spring Security 上下文
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
userDetails, // 用戶信息
null, // 密碼(已驗證,無需存儲)
userDetails.getAuthorities() // 用戶權限(角色)
);
// 設置請求詳情(如 IP、會話 ID)
authentication.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request)
);
// 將認證對象存入上下文:后續(xù)接口權限校驗會從這里獲取用戶信息
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
} catch (Exception e) {
// Token 驗證失?。ㄈ邕^期、篡改),打印日志但不阻斷請求(后續(xù)會返回 401)
logger.error("JWT Token 驗證失敗:" + e.getMessage());
}
// 4. 繼續(xù)執(zhí)行過濾器鏈(讓請求到達后續(xù)接口或過濾器)
filterChain.doFilter(request, response);
}
}七、第五步:重構 SecurityConfig(適配 JWT)
之前的 SecurityConfig 基于 HTTP Basic 登錄,現(xiàn)在需要修改為 JWT 無狀態(tài)登錄,核心調整點:
- 關閉 Session(無狀態(tài)登錄不需要 Session);
- 放行登錄接口(
/api/login); - 將 JWT 過濾器加入過濾器鏈;
- 移除 HTTP Basic 配置,保留統(tǒng)一異常處理。
修改 com.example.firstspringbootproject.config.SecurityConfig 類:
package com.example.firstspringbootproject.config;
import com.example.firstspringbootproject.common.Result;
import com.example.firstspringbootproject.entity.SysUser;
import com.example.firstspringbootproject.filter.JwtAuthenticationFilter;
import com.example.firstspringbootproject.mapper.SysUserMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
@EnableMethodSecurity // 啟用方法級權限控制(如 @PreAuthorize("hasRole('ADMIN')"))
public class SecurityConfig {
@Autowired
private SysUserMapper sysUserMapper;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter; // 自定義 JWT 過濾器
// 1. 密碼編碼器(不變)
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// 2. 用戶詳情服務(不變)
@Bean
public UserDetailsService userDetailsService() {
return username -> {
SysUser sysUser = sysUserMapper.findByUsername(username);
if (sysUser == null) {
throw new UsernameNotFoundException("用戶不存在: " + username);
}
return sysUser;
};
}
// 3. 認證提供者(不變)
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService());
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
// 4. 認證管理器(不變)
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
// 5. 核心規(guī)則配置(重點修改:適配 JWT)
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// 1. 關閉 CSRF(前后端分離必須關)
.csrf(csrf -> csrf.disable())
// 2. 關閉 Session(無狀態(tài)登錄核心:不創(chuàng)建和使用 Session)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
// 3. 配置接口訪問規(guī)則(調整放行接口)
.authorizeHttpRequests(auth -> auth
// ① 放行:接口文檔(Knife4j)、登錄接口
.requestMatchers("/doc.html", "/webjars/**", "/v3/api-docs/**", "/api/login").permitAll()
// ② 管理員接口:僅 ADMIN 可訪問
.requestMatchers("/api/user/all").hasRole("ADMIN")
// ③ 普通用戶接口:USER/ADMIN 可訪問
.requestMatchers("/api/user/**", "/api/product/**").hasAnyRole("USER", "ADMIN")
// ④ 其他接口:必須登錄(Token 有效)
.anyRequest().authenticated()
)
// 4. 加入 JWT 過濾器:在 UsernamePasswordAuthenticationFilter 之前執(zhí)行
// (先驗證 Token,再執(zhí)行后續(xù)認證邏輯)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
// 5. 統(tǒng)一異常處理(不變:未登錄返回 401,權限不足返回 403)
.exceptionHandling(ex -> ex
.authenticationEntryPoint((request, response, authException) -> {
response.setContentType("application/json;charset=UTF-8");
Result<Void> result = Result.error(401, "未登錄或 Token 已過期,請重新登錄");
response.getWriter().write(objectMapper.writeValueAsString(result));
})
.accessDeniedHandler((request, response, accessDeniedException) -> {
response.setContentType("application/json;charset=UTF-8");
Result<Void> result = Result.error(403, "權限不足,無法訪問");
response.getWriter().write(objectMapper.writeValueAsString(result));
})
);
// 關聯(lián)認證提供者
http.authenticationProvider(authenticationProvider());
return http.build();
}
}八、第六步:測試 JWT 無狀態(tài)登錄流程
啟動項目,用 Apifox 測試完整流程,驗證無狀態(tài)登錄和權限控制是否生效:
1. 測試 1:調用登錄接口,獲取 Token
- 請求地址:
http://localhost:8080/api/login - 請求方法:POST
- 請求體(JSON):
{
"username": "admin",
"password": "123456"
}- 響應結果(成功):
{
"code": 200,
"msg": "success",
"data": {
"role": "ROLE_ADMIN",
"expiration": "Token 有效期 2 小時,請及時刷新",
"token": "eyJhbGciOiJIUzUxMiJ9.eyJyb2xlcyI6WyJST0xFX0FETUlOIl0sInN1YiI6ImFkbWluIiwiaWF0IjoxNzYzNDgxMDk0LCJleHAiOjE3NjM0ODgyOTR9.hSxBCTlQo5tUai-knfM2Sh4nVmehizOslcHkvG86jdC-U7-EztskPkF0r4G0DcaTMV3eFcJUu4pCewDdnniq2A"
}
}復制返回的 token,后續(xù)請求會用到。
2. 測試 2:攜帶 Token 訪問管理員接口
- 請求地址:
http://localhost:8080/api/user/all(需 ADMIN 角色) - 請求方法:GET
- 請求頭:添加
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJyb2xlcyI6WyJST0xFX0FETUlOIl0sInN1YiI6ImFkbWluIiwiaWF0IjoxNzYzNDgxMDk0LCJleHAiOjE3NjM0ODgyOTR9.hSxBCTlQo5tUai-knfM2Sh4nVmehizOslcHkvG86jdC-U7-EztskPkF0r4G0DcaTMV3eFcJUu4pCewDdnniq2A(注意Bearer后有空格) - 響應結果(成功):
{
"code": 200,
"msg": "success",
"data": [
{
"id": 1,
"name": "小明",
"age": 20,
"phone": "13800138000"
},
{
"id": 2,
"name": "小紅",
"age": 19,
"phone": "13900139000"
},
{
"id": 3,
"name": "小李",
"age": 22,
"phone": "13700137000"
}
]
}3. 測試 3:普通用戶 Token 訪問管理員接口(權限不足)
- 先用
zhangsan(密碼 123456)調用登錄接口,獲取普通用戶 Token; - 攜帶普通用戶 Token 訪問
http://localhost:8080/api/user/all; - 響應結果(失?。?/strong>:
{
"code": 403,
"msg": "權限不足,無法訪問",
"data": null
}4. 測試 4:Token 過期(模擬)
- 修改
application.yml中jwt.expiration為1000(1 秒過期); - 重新登錄獲取 Token,1 秒后攜帶 Token 訪問接口;
- 響應結果(失敗):
{
"code": 401,
"msg": "未登錄或 Token 已過期,請重新登錄",
"data": null
}九、常見問題與優(yōu)化建議
1. 問題:Token 被盜用怎么辦?
- 原因:JWT Token 一旦生成,在過期前無法主動作廢;
- 解決方案:
- 縮短 Token 過期時間(如 30 分鐘),同時實現(xiàn) Token 刷新接口(用舊 Token 換取新 Token,避免頻繁登錄);
- 維護一個 黑名單(如 Redis),用戶登出或 Token 被盜時,將 Token 加入黑名單,驗證時先檢查是否在黑名單中。
2. 問題:密鑰(secret)泄露怎么辦?
- 原因:密鑰是 JWT 安全的核心,泄露后攻擊者可偽造 Token;
- 解決方案:
- 生產環(huán)境中,密鑰通過 環(huán)境變量 或 配置中心 注入,不寫入代碼或配置文件;
- 使用 非對稱加密算法(如 RS256),用私鑰生成 Token,公鑰驗證 Token,私鑰嚴格保密。
## 十、總結:JWT 無狀態(tài)登錄的核心價值
通過本文的改造,我們實現(xiàn)了 Spring Boot + Spring Security + JWT 的無狀態(tài)登錄,核心優(yōu)勢總結如下:
- 分布式友好:服務器無需存儲 Session,多臺服務器可直接共用 Token 驗證邏輯;
- 前后端分離適配:通過請求頭攜帶 Token,無需依賴 Cookie,適配移動端、小程序等多端場景;
- 安全性提升:Token 包含過期時間和加密簽名,避免身份信息被篡改;
- 擴展性強:Token 可自定義存儲用戶角色、權限等信息,減少數(shù)據(jù)庫查詢次數(shù)。
至此,恭喜你已具備初級程序員開發(fā)水平,可以試著投簡歷找工作啦。
到此這篇關于Spring Boot基于 JWT 優(yōu)化 Spring Security 無狀態(tài)登錄實戰(zhàn)指南的文章就介紹到這了,更多相關Spring Boot JWT Spring Security 無狀態(tài)登錄內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- Spring Boot 2結合Spring security + JWT實現(xiàn)微信小程序登錄
- springboot+jwt+springSecurity微信小程序授權登錄問題
- SpringBoot集成Spring Security用JWT令牌實現(xiàn)登錄和鑒權的方法
- SpringSecurity角色權限控制(SpringBoot+SpringSecurity+JWT)
- SpringBoot3.0+SpringSecurity6.0+JWT的實現(xiàn)
- SpringBoot整合SpringSecurity和JWT和Redis實現(xiàn)統(tǒng)一鑒權認證
- SpringBoot整合SpringSecurity和JWT的示例
- SpringBoot集成SpringSecurity和JWT做登陸鑒權的實現(xiàn)
相關文章
Java?ASM使用logback日志級別動態(tài)切換方案展示
這篇文章主要介紹了Java?ASM使用logback日志級別動態(tài)切換方案展示,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-04-04
關于Spring中@Transactional事務回滾的注意事項
這篇文章主要介紹了關于Spring中@Transactional事務回滾的注意事項,回滾(Rollback)指的是程序或數(shù)據(jù)處理錯誤,將程序或數(shù)據(jù)恢復到上一次正確狀態(tài)的行為?;貪L包括程序回滾和數(shù)據(jù)回滾等類型,需要的朋友可以參考下2023-05-05
Spring?Boot如何在加載bean時優(yōu)先選擇我
這篇文章主要介紹了Spring?Boot如何在加載bean時優(yōu)先選擇我,在?Spring?Boot?應用程序中,我們可以采取三種方式實現(xiàn)自己的?bean?優(yōu)先加載,本文通過實例代碼給大家詳細講解,需要的朋友可以參考下2023-03-03
Java的Spring框架中DAO數(shù)據(jù)訪問對象的使用示例
這篇文章主要介紹了Java的Spring框架中DAO數(shù)據(jù)訪問對象的使用示例,分為在Spring中DOA與JDBC以及與Hibernate的配合使用兩種情況來進行演示,需要的朋友可以參考下2016-03-03
springboot-dubbo cannot be cast to問題及解決
這篇文章主要介紹了springboot-dubbo cannot be cast to問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
SpringBoot中@ConditionalOnBean實現(xiàn)原理解讀
這篇文章主要介紹了SpringBoot中@ConditionalOnBean實現(xiàn)原理,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02
SpringBoot攔截器實現(xiàn)API安全驗證的示例詳解
在開放平臺和第三方集成的項目中,如何確保 API 調用的安全性和可靠性是一個重要課題,本文將詳細介紹如何基于 Spring Boot 攔截器和 HMAC-SHA256 算法,構建一套輕量級但足夠安全的 API 驗簽機制,希望對大家有所幫助2025-11-11

