【架构实战】微服务安全架构:OAuth2.0 + JWT实战
·
一、微服务安全概述
微服务架构下,安全是一个核心挑战:
安全威胁:
- 认证信息泄露
- Token被伪造
- 跨站请求攻击(CSRF)
- 越权访问
二、OAuth2.0协议
1. OAuth2.0授权流程
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ 用户 │ │ 前端 │ │ 认证服务器│ │ 资源服务器│
└────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘
│ │ │ │
│ 1.点击登录 │ │ │
│─────────────>│ │ │
│ │ 2.跳转授权 │ │
│<─────────────│ │ │
│ │ 3.授权 │ │
│─────────────>│ │ │
│ │ 4.返回授权码│ │
│<─────────────│ │ │
│ │ 5.换Token │ │
│ │─────────────>│ │
│ │<────────────│ │
│ │ 6.Token │ │
│<─────────────│ │ │
│ │ 7.请求资源 │ │
│─────────────>│─────────────>│ │
│ │<────────────│ │
│<─────────────│ │ │
2. Spring Security + OAuth2.0实现
依赖配置:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
Security配置:
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**", "/auth/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt.jwtDecoder(jwtDecoder()))
);
return http.build();
}
@Bean
public JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withJwkSetUri("http://auth-server/oauth2/.well-known/jwks.json")
.build();
}
}
三、JWT实战
1. JWT结构
JWT = Header.Payload.Signature
Header: {"alg": "RS256", "typ": "JWT"}
Payload: {"sub": "123", "exp": 1704067200, "roles": ["USER"]}
Signature: RS256(Header.Payload, privateKey)
2. JWT生成
@Service
public class JwtService {
@Value("${jwt.private-key}")
private String privateKey;
public String generateToken(UserDetails user) {
Map<String, Object> claims = new HashMap<>();
claims.put("userId", user.getId());
claims.put("roles", user.getRoles());
return Jwts.builder()
.setClaims(claims)
.setSubject(user.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 3600000))
.signWith(getPrivateKey(), SignatureAlgorithm.RS256)
.compact();
}
private PrivateKey getPrivateKey() {
try {
PKCS8EncodedKeySpec spec =
new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));
KeyFactory factory = KeyFactory.getInstance("RSA");
return factory.generatePrivate(spec);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
3. JWT验证
@Service
public class JwtAuthService {
@Value("${jwt.public-key}")
private String publicKey;
public Authentication authenticate(String token) {
try {
Claims claims = Jwts.parserBuilder()
.setSigningKey(getPublicKey())
.build()
.parseClaimsJws(token)
.getBody();
String username = claims.getSubject();
List<GrantedAuthority> authorities =
((List<?>) claims.get("roles")).stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.collect(Collectors.toList());
UserDetails userDetails =
User.builder().username(username).authorities(authorities).build();
return new UsernamePasswordAuthenticationToken(
userDetails, null, authorities);
} catch (JwtException e) {
throw new JwtAuthenticationException("Invalid token");
}
}
}
四、Token管理
1. Access Token + Refresh Token
@Service
public class TokenService {
public TokenPair generateTokens(User user) {
// Access Token: 短期(1小时)
String accessToken = jwtService.generateAccessToken(user);
// Refresh Token: 长期(7天)
String refreshToken = jwtService.generateRefreshToken(user);
return new TokenPair(accessToken, refreshToken);
}
public String refreshAccessToken(String refreshToken) {
Claims claims = jwtService.validateRefreshToken(refreshToken);
String userId = claims.getSubject();
User user = userService.getById(Long.parseLong(userId));
return jwtService.generateAccessToken(user);
}
}
2. Token黑名单
@Service
public class TokenBlacklistService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
public void addToBlacklist(String token, long expiration) {
redisTemplate.opsForValue().set(
"blacklist:" + token,
"1",
expiration,
TimeUnit.SECONDS
);
}
public boolean isBlacklisted(String token) {
return Boolean.TRUE.equals(
redisTemplate.hasKey("blacklist:" + token)
);
}
}
五、微服务认证
1. 网关统一认证
@Component
public class JwtAuthFilter implements GatewayFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = extractToken(exchange.getRequest());
if (token != null) {
try {
Authentication auth = jwtAuthService.authenticate(token);
ServerWebExchangeUtils.put(exchange,
"AUTHENTICATION", auth);
} catch (Exception e) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
}
return chain.filter(exchange);
}
}
2. Feign传递Token
@Configuration
public class FeignConfig {
@Bean
public RequestInterceptor requestInterceptor() {
return template -> {
// 从上下文获取Token
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.getCredentials() instanceof String) {
String token = (String) auth.getCredentials();
template.header("Authorization", "Bearer " + token);
}
};
}
}
六、安全最佳实践
1. HTTPS强制
# application.yml
server:
ssl:
enabled: true
key-store: classpath:keystore.p12
key-store-password: password
key-store-type: PKCS12
2. 密码加密
@Service
public class PasswordEncoder {
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
// 使用BCrypt
@Bean
public PasswordEncoder bcryptEncoder() {
return new BCryptPasswordEncoder(12);
}
3. 限流防刷
@Component
public class RateLimitFilter implements GatewayFilter {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String ip = getClientIp(exchange.getRequest());
String key = "ratelimit:" + ip;
Long count = redisTemplate.opsForValue().increment(key);
if (count != null && count == 1) {
redisTemplate.expire(key, 60, TimeUnit.SECONDS);
}
if (count != null && count > 100) {
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
}
七、总结
微服务安全架构核心要点:
- OAuth2.0:标准授权协议
- JWT:无状态Token
- 网关认证:统一入口
- Token管理:有效期+黑名单
个人观点,仅供参考
更多推荐



所有评论(0)