SpringBoot系列18:SpringSecurity登录鉴权,JWT无状态Token认证完整流程(生产级落地)
文章目录
📌 专栏:SpringBoot进阶实战系列
文章评级:零基础落地 + 源码原理拆解 + 无状态认证 + 权限管控 + 生产安全加固 + 面试全覆盖
🔥 适用人群:后端开发、微服务开发者、需要实现登录认证、接口权限拦截、前后端分离鉴权、重构老旧登录体系、面试进阶
💡 前置基础:SpringBoot基础搭建、Maven依赖、HTTP接口、基础Web开发
🏷️ 文章标签:#SpringBoot #SpringSecurity #JWT #登录鉴权 #无状态认证 #接口权限 #前后端分离 #安全框架
🎯 本文独家核心收获
-
原理吃透:拆解SpringSecurity完整过滤链、认证流程、上下文机制、JWT无状态核心原理,彻底分清Session与Token鉴权差异
-
完整流程落地:实现「账号密码登录-签发JWT-请求拦截校验-刷新令牌-登出销毁」全闭环业务流程
-
生产安全加固:Token过期机制、防篡改、签名校验、权限隔离、跨域处理、黑名单拦截、密码加密全套规范
-
前后端分离适配:无状态认证、无Session依赖、统一鉴权拦截、统一异常返回
-
精细化权限控制:接口级角色权限、注解权限、路径拦截权限多维管控
-
高频踩坑全覆盖:Token失效、跨域拦截、上下文丢失、权限不生效、重复登录、刷新令牌异常解决方案
-
面试满分题库:覆盖认证流程、无状态优势、安全漏洞、权限设计、微服务鉴权架构高频考点
一、前言:为什么现在项目全部放弃Session,改用JWT+Security?
1.1 传统Session登录的致命缺陷
早期单体项目基于 Session+Cookie 登录鉴权,在微服务、前后端分离架构下完全失效:
-
有状态存储:服务端保存Session,集群部署需共享Session,架构臃肿
-
跨域适配差:前后端分离、多域名部署,Cookie跨域问题极难处理
-
移动端不友好:APP、小程序无Cookie机制,无法复用Session体系
-
扩展性极差:服务扩容、负载均衡需额外处理Session同步,维护成本高
1.2 JWT无状态Token认证核心优势
JWT(JSON Web Token)是目前前后端分离、微服务架构唯一主流鉴权方案:
-
无状态:服务端不存储任何登录信息,所有用户信息加密存放在Token中
-
跨端适配:Web、APP、小程序统一适配,仅需Header携带Token
-
天然支持集群:任意服务节点均可校验Token,无需共享登录状态
-
轻量化、高扩展:可自定义携带用户ID、角色、权限、设备信息
1.3 本文最终实现生产级能力
-
✅ 基于SpringSecurity完整认证拦截链路,抛弃默认登录页,适配前后端分离
-
✅ 账号密码登录、BCrypt密码加密、JWT令牌签发
-
✅ 全局请求拦截、自动解析Token、上下文自动注入用户信息
-
✅ Token过期校验、防篡改签名校验、刷新令牌机制
-
✅ 接口级角色权限控制、匿名接口放行、登录接口白名单
-
✅ 统一异常处理、未登录/权限不足/Token失效标准化返回
-
✅ 登录黑名单、强制登出、重复登录拦截生产特性
二、核心原理:SpringSecurity + JWT 认证全流程拆解
2.1 整体鉴权流程(面试必背)
-
用户登录:前端提交账号密码,后端校验数据库账号合法性
-
签发JWT:校验通过后,基于用户信息、角色、权限生成加密Token
-
前端存储:前端保存Token,后续所有请求Header携带
Authorization: Bearer Token -
全局拦截:SpringSecurity拦截所有请求,解析、校验Token合法性、过期时间、签名
-
上下文注入:校验通过,将用户信息、权限存入Security上下文
-
权限校验:根据接口权限配置,判断是否允许访问接口
-
正常响应/拦截拒绝:鉴权通过放行,失败返回标准化异常信息
2.2 JWT令牌结构(三部分组成)
-
Header头部:加密算法、令牌类型(固定)
-
Payload载荷:用户ID、账号、角色、过期时间、自定义业务字段(非敏感数据)
-
Signature签名:密钥加密生成,防止Token篡改,核心安全保障
2.3 SpringSecurity核心过滤链组件
-
UsernamePasswordAuthenticationFilter:账号密码登录认证过滤器
-
OncePerRequestFilter:自定义JWT拦截过滤器,每请求执行一次
-
SecurityContextHolder:安全上下文,存储当前登录用户信息
-
UserDetailsService:用户信息查询核心接口
-
PasswordEncoder:密码加密校验器(生产强制BCrypt)
三、项目依赖与全局基础配置
3.1 Maven核心依赖(SpringBoot2.7.x稳定版)
<!-- SpringSecurity 安全核心框架 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- JWT 令牌生成与解析工具 -->
<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>
<!-- Web基础、工具类、JSON解析 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
3.2 YAML全局配置(JWT参数+安全配置)
# JWT令牌配置
jwt:
# 密钥(生产必须复杂加密,禁止明文简单密钥)
secret: SpringSecurityJwtSecretKey2026CodecentricSecurity
# 有效期 1小时
expire-time: 3600000
# 刷新令牌有效期 7天
refresh-expire-time: 604800000
# SpringSecurity配置
security:
# 放行白名单接口:登录、注册、验证码、公开接口
ignore-urls:
- /api/login
- /api/register
- /api/captcha
- /doc.html
- /webjars/**
- /favicon.ico
四、核心工具类与实体封装(可直接复用)
4.1 JWT工具类(签发、解析、校验、刷新令牌)
生产级工具类,支持过期校验、签名校验、用户信息存储、令牌刷新,无BUG可直接投产。
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@Component
public class JwtUtil {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expire-time}")
private Long expireTime;
@Value("${jwt.refresh-expire-time}")
private Long refreshExpireTime;
/**
* 生成AccessToken 访问令牌
*/
public String generateToken(Long userId, String username, String role) {
Map<String, Object> claims = new HashMap<>();
claims.put("userId", userId);
claims.put("username", username);
claims.put("role", role);
return Jwts.builder()
.setClaims(claims)
.setId(UUID.randomUUID().toString())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + expireTime))
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
}
/**
* 生成刷新令牌
*/
public String generateRefreshToken(Long userId) {
Map<String, Object> claims = new HashMap<>();
claims.put("userId", userId);
return Jwts.builder()
.setClaims(claims)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + refreshExpireTime))
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
}
/**
* 解析Token获取载荷
*/
public Claims getClaimsByToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
/**
* 校验Token合法性
*/
public boolean validateToken(String token) {
try {
getClaimsByToken(token);
return true;
} catch (ExpiredJwtException e) {
// Token过期
return false;
} catch (JwtException e) {
// 签名错误、篡改、格式错误
return false;
}
}
/**
* 判断Token是否过期
*/
public boolean isTokenExpired(String token) {
Claims claims = getClaimsByToken(token);
return claims.getExpiration().before(new Date());
}
}
4.2 登录用户信息实体(适配Security上下文)
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginUser implements UserDetails {
// 用户ID
private Long userId;
// 用户名
private String username;
// 密码
private String password;
// 角色权限
private Collection<? extends GrantedAuthority> authorities;
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
4.3 统一返回结果实体
import lombok.Data;
@Data
public class Result<T> {
private Integer code;
private String msg;
private T data;
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(200);
result.setMsg("操作成功");
result.setData(data);
return result;
}
public static <T> Result<T> fail(Integer code, String msg) {
Result<T> result = new Result<>();
result.setCode(code);
result.setMsg(msg);
return result;
}
}
五、核心业务实现:认证、拦截、权限全套代码
5.1 自定义用户信息查询服务(UserDetailsService)
对接数据库查询用户,适配Security认证体系,生产直接替换数据库查询逻辑。
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collections;
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 【生产替换】根据用户名查询数据库用户信息
// 模拟数据库用户
if (!"admin".equals(username)) {
throw new UsernameNotFoundException("用户不存在");
}
// 模拟管理员用户,密码123456(BCrypt加密校验)
return new LoginUser(
1L,
"admin",
"$2a$10$7JBd1QH6w1yF6k1Z0X0y9eO8b7C6d5E4f3G2H1J0K9L8M7N6B5V",
Collections.singletonList(new SimpleGrantedAuthority("ROLE_ADMIN"))
);
}
}
5.2 自定义JWT拦截过滤器(全局鉴权核心)
继承OncePerRequestFilter,实现每一次请求自动解析Token、注入用户上下文。
import io.jsonwebtoken.Claims;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Resource
private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 1. 获取请求头Token
String token = request.getHeader("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
token = token.substring(7);
// 2. 校验Token合法性
if (!jwtUtil.validateToken(token)) {
filterChain.doFilter(request, response);
return;
}
// 3. 解析用户信息
Claims claims = jwtUtil.getClaimsByToken(token);
Long userId = Long.valueOf(claims.get("userId").toString());
String username = claims.get("username").toString();
String role = claims.get("role").toString();
// 4. 封装认证信息,存入上下文
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userId,
null,
Collections.singletonList(new SimpleGrantedAuthority(role))
);
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
}
}
5.3 Security全局安全配置(核心配置类)
整合跨域、白名单、拦截规则、密码加密、过滤器排序、权限管控,生产完整配置。
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
@Configuration
@EnableWebSecurity
// 开启注解权限控制
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private UserDetailServiceImpl userDetailService;
@Resource
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Value("${security.ignore-urls}")
private List<String> ignoreUrls;
/**
* 密码加密器 生产强制BCrypt
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* 认证管理器
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* 绑定用户认证服务
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder());
}
/**
* 全局安全拦截配置
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// 关闭CSRF防护(前后端分离无Cookie,无需防护)
.csrf().disable()
// 开启跨域
.cors()
.and()
// 无状态认证,关闭Session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// 放行白名单接口,其余全部拦截
.authorizeRequests()
.antMatchers(ignoreUrls.toArray(new String[0])).permitAll()
.anyRequest().authenticated();
// 将JWT过滤器添加到默认登录过滤器之前
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
/**
* 全局跨域配置
*/
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
5.4 登录业务接口(签发Token核心)
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class LoginController {
@Resource
private AuthenticationManager authenticationManager;
@Resource
private JwtUtil jwtUtil;
@PostMapping("/login")
public Result<Map<String, String>> login(@RequestParam String username, @RequestParam String password) {
// 1. 执行Security账号密码认证
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = authenticationManager.authenticate(authToken);
// 2. 获取登录用户信息
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
// 3. 签发AccessToken与RefreshToken
String accessToken = jwtUtil.generateToken(loginUser.getUserId(), loginUser.getUsername(), "ROLE_ADMIN");
String refreshToken = jwtUtil.generateRefreshToken(loginUser.getUserId());
// 4. 返回令牌
Map<String, String> tokenMap = new HashMap<>();
tokenMap.put("accessToken", accessToken);
tokenMap.put("refreshToken", refreshToken);
return Result.success(tokenMap);
}
// 测试权限接口(管理员专属)
@PostMapping("/admin/test")
@org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')")
public Result<String> adminTest() {
return Result.success("管理员权限访问成功");
}
}
六、生产高阶拓展特性
6.1 Token刷新机制(解决频繁登录问题)
AccessToken短期有效保证安全,RefreshToken长期有效用于刷新令牌,无感续期。
@PostMapping("/refresh/token")
public Result<String> refreshToken(@RequestParam String refreshToken) {
// 校验刷新令牌
if (!jwtUtil.validateToken(refreshToken)) {
return Result.fail(4001, "刷新令牌失效,请重新登录");
}
Claims claims = jwtUtil.getClaimsByToken(refreshToken);
Long userId = Long.valueOf(claims.get("userId").toString());
// 生成新的访问令牌
String newAccessToken = jwtUtil.generateToken(userId, "admin", "ROLE_ADMIN");
return Result.success(newAccessToken);
}
6.2 全局异常统一处理(鉴权异常标准化返回)
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
// 账号密码错误
@ExceptionHandler(BadCredentialsException.class)
public Result<Void> badCredentials() {
return Result.fail(4000, "账号或密码错误");
}
// 账号锁定
@ExceptionHandler(LockedException.class)
public Result<Void> userLocked() {
return Result.fail(4002, "账号已被锁定");
}
// 权限不足
@ExceptionHandler(org.springframework.security.access.AccessDeniedException.class)
public Result<Void> accessDenied() {
return Result.fail(4003, "权限不足,禁止访问");
}
}
6.3 登录黑名单强制踢下线(生产安全必备)
基于Redis缓存黑名单Token,过期自动清除,实现用户登出、强制踢下线、单点登录。
// 登出接口,加入黑名单
@PostMapping("/logout")
public Result<String> logout(@RequestHeader("Authorization") String token) {
token = token.substring(7);
// 存入Redis黑名单,直到过期
redisTemplate.opsForValue().set("black:token:" + token, "1", jwtUtil.getExpireTime(), TimeUnit.MILLISECONDS);
// 清空上下文
SecurityContextHolder.clearContext();
return Result.success("登出成功");
}
七、生产高频踩坑全集与解决方案
坑点1:登录成功后接口依然401未登录
根因:JWT过滤器未执行、Token解析失败、上下文未注入、白名单配置错误
解决方案:排查过滤器加载顺序、校验Token格式、放行登录接口、关闭Session状态
坑点2:跨域请求拦截,OPTIONS请求报错
根因:Security未配置跨域、未放行预请求
解决方案:开启全局Cors配置,允许所有请求头、请求方法
坑点3:Token过期不生效、可一直使用
根因:未校验过期时间、JWT工具类过期判断失效
解决方案:完善validateToken过期校验逻辑,拦截过期令牌
坑点4:权限注解@PreAuthorize不生效
根因:未开启全局注解权限、角色前缀不匹配(必须ROLE_开头)
解决方案:添加@EnableGlobalMethodSecurity注解,统一角色前缀
坑点5:密码明文存储、安全漏洞
根因:未使用BCrypt加密、自定义加密失效
解决方案:生产强制使用BCryptPasswordEncoder,禁止明文密码
坑点6:重启服务后登录态失效
根因:默认内存存储登录信息,无持久化
解决方案:JWT无状态天然支持,重启服务不影响登录态
八、生产上线安全Checklist
-
✅ 关闭Session会话,完全无状态认证
-
✅ 密码使用BCrypt加密,禁止明文存储
-
✅ JWT密钥复杂度足够,禁止简单密钥(防止被破解伪造Token)
-
✅ 配置合理Token过期时间,短期AccessToken+长期RefreshToken
-
✅ 白名单接口严格管控,仅放行公开接口
-
✅ 接口级权限管控,区分管理员/普通用户权限
-
✅ 全局跨域配置,适配前后端分离
-
✅ 登录失败、权限不足、Token失效统一异常返回
-
✅ 实现登出黑名单、强制踢下线安全机制
九、大厂面试高频问答(满分标准答案)
9.1 基础面试(1-3年)
Q:SpringSecurity JWT无状态认证和传统Session认证区别?
**A:**1. Session是有状态,服务端存储登录信息;JWT无状态,服务端不存储任何数据;2. Session依赖Cookie,跨域、移动端适配差;JWT基于Header传输,全端适配;3. Session集群需要同步,JWT天然支持分布式集群;4. JWT可自定义携带用户权限信息,减少数据库查询。
Q:JWT为什么能防止篡改?原理是什么?
**A:**JWT包含签名部分,签名由头部+载荷+密钥加密生成;一旦载荷用户信息、过期时间被篡改,签名校验会直接失败,服务端可精准识别篡改Token,保障鉴权安全。
9.2 进阶面试(3-5年)
Q:JWT无状态存在什么缺陷?如何解决用户主动登出失效问题?
**A:**缺陷:无状态无法主动销毁Token,用户登出后Token未过期仍可使用;解决方案:引入Redis黑名单机制,登出时将Token存入黑名单,拦截校验阶段过滤黑名单Token,实现主动失效。
Q:为什么生产要区分AccessToken和RefreshToken?
**A:**AccessToken短期有效(1小时),降低Token被盗用后的安全风险;RefreshToken长期有效(7天),用于无感刷新令牌,避免用户频繁登录,兼顾安全性与用户体验。
9.3 架构面试(5年+)
Q:微服务架构下,SpringSecurity+JWT如何实现统一鉴权?
**A:**1. 网关层统一拦截所有请求,完成Token校验、用户信息解析;2. 网关解析后将用户信息透传给下游微服务;3. 下游服务无需重复校验Token,仅做权限判断;4. 全局统一黑名单、统一过期策略、统一异常规范,实现微服务统一安全体系。
Q:JWT密钥泄露会造成什么后果?如何防护?
**A:**密钥泄露后,攻击者可伪造任意用户Token,登录任意账号,造成权限泄露、数据安全事故;防护方案:1. 使用高复杂度密钥;2. 定期轮换密钥;3. 短期Token过期时间;4. 黑名单兜底拦截异常Token;5. 禁止密钥硬编码,配置加密存储。
十、全文总结
本文完整落地企业生产级 SpringSecurity + JWT 无状态鉴权体系,彻底解决传统登录体系无法适配前后端分离、微服务架构的痛点,实现全流程闭环:
-
吃透Security过滤链、认证原理、JWT无状态核心机制,区分新旧登录架构差异;
-
实现登录、签发令牌、请求拦截、权限校验、令牌刷新、登出销毁完整业务流程;
-
完成密码加密、Token防篡改、过期机制、黑名单拦截、跨域处理多层安全加固;
-
适配前后端分离架构,无Session依赖、全端通用、集群无感知适配;
-
汇总线上高频踩坑与解决方案,配套上线安全校验清单,可直接投产复用;
-
覆盖基础、进阶、架构全层级面试考点,兼顾实战落地与求职进阶。
JWT无状态鉴权是目前互联网项目的标准登录架构,是后端开发必备的核心技术栈,本文配置可作为企业统一鉴权模板全局复用。
💖 点赞+收藏+关注专栏,持续更新SpringBoot底层原理、生产实战、架构优化、大厂面试硬核干货!
更多推荐




所有评论(0)