Spring Cloud Security实战:OAuth2与JWT集成指南
Spring Cloud Security 安全控制实战指南
一、OAuth2.0集成
核心概念
OAuth2.0是当前微服务架构中最流行的授权框架,Spring Cloud Security提供了完整的OAuth2.0实现方案。
授权服务器配置
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("clientapp")
.secret(passwordEncoder().encode("123456"))
.authorizedGrantTypes("password", "refresh_token")
.scopes("read", "write")
.accessTokenValiditySeconds(3600);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
实践建议:
- 生产环境务必使用JDBC存储客户端信息而非内存存储
- 合理设置token有效期,通常access_token 2小时,refresh_token 7天
- 建议采用PKCE扩展增强公共客户端安全性
二、JWT支持
JWT优势
- 自包含:减少身份验证服务器查询
- 无状态:适合分布式系统
- 可验证:数字签名保证完整性
配置JWT令牌
@Configuration
public class JwtConfig {
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("my-secret-key"); // 生产环境使用非对称加密
return converter;
}
}
JWT最佳实践:
- 敏感信息不要放入JWT
- 使用非对称加密(RS256)而非对称加密(HS256)
- 设置合理的过期时间
- 实现token黑名单机制用于注销
三、资源服务器配置
基础配置
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated();
}
}
方法级安全控制
@RestController
@RequestMapping("/api")
public class UserController {
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/users")
public List<User> listUsers() {
// ...
}
@PostAuthorize("returnObject.username == principal.username")
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
// ...
}
}
安全建议:
- 遵循最小权限原则
- 敏感操作增加二次验证
- 定期审计权限分配
四、API安全防护
1. 签名验证
public class ApiSignInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
String sign = request.getHeader("X-API-SIGN");
String timestamp = request.getHeader("X-API-TIMESTAMP");
// 验证时间戳有效性
if(!validateTimestamp(timestamp)) {
throw new ApiException("无效请求");
}
// 验证签名
String expectedSign = generateSign(request, timestamp);
if(!expectedSign.equals(sign)) {
throw new ApiException("签名错误");
}
return true;
}
}
2. 防重放攻击
public class ReplayAttackFilter extends OncePerRequestFilter {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) {
String nonce = request.getHeader("X-API-NONCE");
if(StringUtils.isEmpty(nonce)) {
throw new ApiException("缺少防重放参数");
}
// 检查nonce是否已使用
Boolean result = redisTemplate.opsForValue()
.setIfAbsent("nonce:"+nonce, "1", 5, TimeUnit.MINUTES);
if(Boolean.FALSE.equals(result)) {
throw new ApiException("请求已过期或重复");
}
filterChain.doFilter(request, response);
}
}
3. 限流防护
@Configuration
public class RateLimitConfig {
@Bean
public FilterRegistrationBean<RateLimitFilter> rateLimitFilter() {
FilterRegistrationBean<RateLimitFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new RateLimitFilter());
registration.addUrlPatterns("/api/*");
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}
}
public class RateLimitFilter implements Filter {
private RateLimiter rateLimiter = RateLimiter.create(100); // 每秒100个请求
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain) {
if(!rateLimiter.tryAcquire()) {
((HttpServletResponse)response).sendError(429, "请求过于频繁");
return;
}
chain.doFilter(request, response);
}
}
API安全最佳实践:
- 全站HTTPS加密
- 敏感参数加密传输
- 关键操作日志记录
- 定期安全扫描和渗透测试
五、安全监控与审计
安全事件日志
@Aspect
@Component
public class SecurityAuditAspect {
@Autowired
private AuditLogService auditLogService;
@AfterReturning(
pointcut = "@annotation(org.springframework.security.access.prepost.PreAuthorize)",
returning = "result")
public void auditSuccess(JoinPoint jp, Object result) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
auditLogService.log(auth.getName(),
jp.getSignature().getName(),
"SUCCESS");
}
@AfterThrowing(
pointcut = "@annotation(org.springframework.security.access.prepost.PreAuthorize)",
throwing = "ex")
public void auditFailure(JoinPoint jp, Exception ex) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
auditLogService.log(auth != null ? auth.getName() : "ANONYMOUS",
jp.getSignature().getName(),
"FAILURE: " + ex.getMessage());
}
}
总结
Spring Cloud Security为微服务架构提供了全面的安全解决方案:
- OAuth2.0 + JWT实现安全的身份认证和授权
- 资源服务器细粒度权限控制
- 多层次的API安全防护体系
- 完善的安全监控和审计机制
在实际项目中,建议根据业务需求组合使用这些安全组件,并定期进行安全评估和升级,以应对不断变化的安全威胁。