微服务安全(OAuth2 + JWT)

微服务安全(OAuth2 + JWT)


文章目录

微服务安全(OAuth2 + JWT)

第一章:安全设计的必要性——像游乐园的安检门
第二章:OAuth2 的四张“门票”

1. 密码模式(直接买票)
2. 授权码模式(第三方代购)
3. 客户端模式(员工通道)
4. 简化模式(快速通道)

第三章:JWT——防伪会员卡

代码示例:生成JWT
代码示例:验证JWT

第四章:整合Spring Security——安装安检设备

步骤1:添加依赖
步骤2:配置安全规则

第五章:权限控制——划分VIP区域

方法级权限注解
网关统一鉴权

第六章:常见安全问题与对策

问题1:令牌泄露
问题2:密码明文传输
问题3:权限配置错误

第七章:总结与最佳实践


第一章:安全设计的必要性——像游乐园的安检门

想象你运营一家主题乐园:

**游客(用户)**需要门票(凭证)才能进入
**不同区域(服务)**需要不同权限(VIP区需额外手环)
**黄牛(攻击者)**可能伪造门票混入

OAuth2 + JWT 就是游乐园的“智能安检系统”,它解决了三个核心问题:

如何安全分发门票(认证)
如何验证门票真伪(鉴权)
如何限制黄牛倒卖(令牌时效性)


第二章:OAuth2 的四张“门票”

OAuth2 定义了四种授权方式,就像游乐园的不同购票渠道:

1. 密码模式(直接买票)

适用场景:自家APP登录

// 密码模式获取令牌  
POST /oauth/token  
grant_type=password&username=user&password=123&client_id=app  

2. 授权码模式(第三方代购)

适用场景:微信登录、Google登录
流程:

跳转到第三方登录页
用户授权后返回授权码
用授权码兑换令牌

3. 客户端模式(员工通道)

适用场景:服务间内部通信

POST /oauth/token  
grant_type=client_credentials&client_id=service&client_secret=abc  

4. 简化模式(快速通道)

适用场景:纯前端应用(无服务端)


第三章:JWT——防伪会员卡

JWT(JSON Web Token)就像一张加密的会员卡,包含:

卡面信息(Payload):用户ID、权限、有效期
防伪标识(签名):用密钥生成,无法伪造

代码示例:生成JWT

public String createJwt(User user) {
              
    // 当前时间与过期时间  
    Date now = new Date();  
    Date expire = new Date(now.getTime() + 3600 * 1000);  

    // 构建JWT(像打印会员卡)  
    return Jwts.builder()  
        .setHeaderParam("typ", "JWT")  
        .setSubject(user.getId().toString())  
        .claim("role", user.getRole())  // 自定义信息  
        .setIssuedAt(now)  
        .setExpiration(expire)  
        .signWith(SignatureAlgorithm.HS256, "your-secret-key") // 签名密钥  
        .compact();  
}  

代码示例:验证JWT

public boolean validateJwt(String token) {
              
    try {
              
        // 解析并验证签名(像扫码验票)  
        Jws<Claims> claims = Jwts.parser()  
            .setSigningKey("your-secret-key")  
            .parseClaimsJws(token);  

        // 检查是否过期  
        return !claims.getBody().getExpiration().before(new Date());  
    } catch (Exception e) {
              
        return false; // 令牌无效  
    }  
}  

第四章:整合Spring Security——安装安检设备

步骤1:添加依赖

<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-security</artifactId>  
</dependency>  
<dependency>  
    <groupId>org.springframework.security.oauth</groupId>  
    <artifactId>spring-security-oauth2</artifactId>  
    <version>2.5.2.RELEASE</version>  
</dependency>  

步骤2:配置安全规则

@Configuration  
@EnableAuthorizationServer  // 开启认证服务器  
public class AuthConfig extends AuthorizationServerConfigurerAdapter {
              

    @Autowired  
    private AuthenticationManager authenticationManager;  

    // 配置客户端信息(像登记合作售票点)  
    @Override  
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
              
        clients.inMemory()  
            .withClient("web-app")  
            .secret("{noop}web-secret")  // {noop}表示明文密码  
            .authorizedGrantTypes("password", "refresh_token")  
            .scopes("read", "write")  
            .accessTokenValiditySeconds(3600);  
    }  

    // 配置令牌生成方式  
    @Override  
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
              
        endpoints  
            .authenticationManager(authenticationManager)  
            .accessTokenConverter(jwtAccessTokenConverter());  
    }  

    // 使用JWT替换默认令牌  
    @Bean  
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
              
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();  
        converter.setSigningKey("your-secret-key");  // 签名密钥  
        return converter;  
    }  
}  

第五章:权限控制——划分VIP区域

方法级权限注解

@PreAuthorize("hasRole('ADMIN')")  // 仅管理员可访问  
@DeleteMapping("/user/{id}")  
public void deleteUser(@PathVariable Long id) {
              
    userService.delete(id);  
}  

网关统一鉴权

@Component  
public class AuthFilter implements GlobalFilter {
              

    @Override  
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
              
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");  
        if (token == null || !validateJwt(token)) {
              
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);  
            return exchange.getResponse().setComplete();  
        }  

        // 从JWT解析用户角色  
        Claims claims = parseJwt(token);  
        if (!claims.get("role").equals("VIP")) {
              
            exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);  
            return exchange.getResponse().setComplete();  
        }  

        return chain.filter(exchange);  
    }  
}  

第六章:常见安全问题与对策

问题1:令牌泄露

对策

设置短有效期(如1小时)
使用HTTPS传输
提供刷新令牌机制

问题2:密码明文传输

解决

// 客户端必须加密传输  
@PostMapping("/login")  
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
                
    String encryptedPassword = encrypt(request.getPassword()); // RSA加密  
    // 验证逻辑...  
}  

问题3:权限配置错误

检查

定期审计接口权限
使用RBAC(基于角色的访问控制)模型


第七章:总结与最佳实践

OAuth2 + JWT 的组合就像为微服务打造了一套“智能安检系统”:

OAuth2 负责安全分发门票
JWT 确保门票无法伪造
Spring Security 提供安检设备支持

最佳实践建议

生产环境使用非对称加密(如RSA)签名JWT
为不同服务分配独立客户端ID
监控异常令牌使用行为


下一篇文章我们将探讨性能调优技巧——就像优化游乐设施排队系统,让游客玩得更顺畅。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容