com.example.demo
├── config
│ └── SecurityConfig.java
├── controller
│ ├── AuthController.java
│ ├── DemoController.java
│ └── HelloController.java
├── entity
│ └── User.java
├── filter
│ └── JwtAuthenticationFilter.java
├── handler
│ ├── CustomAccessDeniedHandler.java
│ └── CustomLoginFailureHandler.java
├── mapper
│ └── UserMapper.java
├── point
│ └── CustomAuthenticationEntryPoint.java
├── service
│ └── MyUserDetailsService.java
├── utils
│ ├── JwtUtils.java
│ └── TokenBlacklist.java
└── SecurityDemoApplication.java
用户通过 /auth/login 接口提交用户名密码,系统验证通过后,签发一个包含用户名和角色信息的 JWT:
String token = Jwts.builder()
.setSubject(username)
.claim("role", role)
.setIssuedAt(now)
.setExpiration(expiry)
.signWith(key, SignatureAlgorithm.HS256)
.compact();
前端需将该 Token 保存在本地(如 localStorage)并在后续请求中通过 Authorization: Bearer xxxxxx 的方式传递。
JWT 鉴权通过 JwtAuthenticationFilter 实现,它继承 OncePerRequestFilter,会在每次请求时验证 Token 的合法性,并将用户信息注入 Spring Security 上下文中:
String header = request.getHeader("Authorization");
if (header != null && header.startsWith("Bearer ")) {
Claims claims = jwtUtils.parseToken(token);
// 验证通过后构建Authentication对象
UsernamePasswordAuthenticationToken authToken = ...
SecurityContextHolder.getContext().setAuthentication(authToken);
}
前端 -> 登录接口 -> JWT签发 -> 保存Token
-> 带Token访问受保护接口 -> 过滤器校验 -> 放行或拒绝
Spring Security 支持使用 @PreAuthorize 注解实现方法级权限控制:
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin")
public String adminApi() {
return "管理员接口";
}
确保在 SecurityConfig 中启用:
@EnableMethodSecurity
X-Refresh-Token每次成功访问受保护接口时,过滤器判断 Token 剩余时间是否低于阈值(如10分钟),如果是则自动签发新 Token 并通过响应头 X-Refresh-Token 返回:
if (jwtUtils.shouldRefresh(claims.getExpiration())) {
String newToken = jwtUtils.generateToken(username, role);
response.setHeader("X-Refresh-Token", newToken);
}
前端监听 X-Refresh-Token 并自动更新本地 Token。
redisTemplate.opsForValue().set("blacklist:" + token, "1", ttl, TimeUnit.MILLISECONDS);
if (redisTemplate.hasKey("blacklist:" + token)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
{
"code": 401,
"message": "未登录或Token无效"
}
1、AuthenticationManager Bean 不存在?
手动构造并通过 @Bean 注入
Keys.secretKeyFor(SignatureAlgorithm.HS256) 或 ≥32位字符串
git pull origin main --allow-unrelated-histories
-
https://gitee.com/nidayeyo/spring-security-demo
往期推荐
SpringBoot 3.x 集成 Flowable 7.x:流程设计、部署、启动及完成实战
搞定 Nginx 生产部署:避坑指南 + 最佳实践
从零手撸 SpringBoot 日志分析系统:打造高性能慢SQL检测神器
Spring 官宣正式弃用 RestTemplate
支付宝:多线程事务怎么回滚?说用@Transactional可以回去等通知了!
Spring Boot 实现微信登录,So Easy !

