
在企业级微服务应用中,通常会采用spring boot构建多个微服务,并使用keycloak等工具作为独立的授权服务。一种常见的误区是,在每个微服务内部,为了进行身份验证和获取jwt令牌,会频繁地调用授权服务;并且在每个api端点接收到请求时,再次调用授权服务来验证jwt令牌并获取权限信息。当系统面临百万级用户并发访问时,这种模式极易导致授权服务成为整个系统的性能瓶颈,使其不堪重负。简单地增加授权服务的实例数量进行负载均衡,并非解决此类问题的最佳实践。
要解决上述挑战,关键在于深入理解JWT(JSON Web Token)和OAuth2协议的核心设计理念。
JWT的自包含性与签名机制: JWT是一种紧凑、URL安全的方式,用于在各方之间安全地传输信息。它由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。
签名的存在使得JWT具有防篡改性。一旦JWT被签发,任何对头部或载荷的修改都会导致签名验证失败。
OAuth2与JWT的结合: OAuth2是一种授权框架,而JWT常被用作OAuth2中的访问令牌(Access Token)。授权服务(如Keycloak)负责颁发这些JWT。
关键在于,JWT一旦被授权服务签发并签名,资源服务器(即你的其他微服务)可以独立地验证这个JWT的有效性,而无需每次都去询问授权服务。这是因为:
基于上述原理,以下是解决授权服务负载问题的工业级最佳实践:
JWT的生命周期管理与重用:
资源服务器的本地JWT验证: 这是减轻授权服务压力的核心。资源服务器不应在每次请求时都调用授权服务来验证JWT。相反,它应该:
在Spring Boot微服务中,可以使用Spring Security来集成Keycloak并实现本地JWT验证。
// build.gradle (或 pom.xml) 中添加依赖
// implementation 'org.springframework.boot:spring-boot-starter-security'
// implementation 'org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure' // For older Spring Boot versions
// For newer Spring Boot versions (Spring Security 5.x+):
// implementation 'org.springframework.security:spring-security-oauth2-resource-server'
// implementation 'org.springframework.security:spring-security-oauth2-jose'
// application.yml (或 application.properties) 配置
spring:
security:
oauth2:
resourceserver:
jwt:
# Keycloak的JWKS URI,用于获取公钥
# 例如: http://localhost:8080/realms/your-realm/protocol/openid-connect/certs
jwk-set-uri: http://keycloak-host:8080/realms/your-realm/protocol/openid-connect/certs
# 如果Keycloak配置了issuer-uri,也可以直接使用issuer-uri
# issuer-uri: http://keycloak-host:8080/realms/your-realm
# jwk-set-uri会自动从issuer-uri/.well-known/openid-configuration中发现
// Spring Security 配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class ResourceServerConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorizeRequests ->
authorizeRequests
// 允许所有请求访问公共端点
.requestMatchers("/public/**").permitAll()
// 其他所有请求都需要认证
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2ResourceServer ->
oauth2ResourceServer
.jwt(jwt -> jwt.jwkSetUri("http://keycloak-host:8080/realms/your-realm/protocol/openid-connect/certs"))
// 或者使用issuer-uri,Spring Security会自行发现JWKS URI
// .jwt(jwt -> jwt.issuerUri("http://keycloak-host:8080/realms/your-realm"))
);
return http.build();
}
}
// 在控制器中使用 @PreAuthorize 进行权限控制
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyResourceController {
@GetMapping("/admin/data")
@PreAuthorize("hasRole('ADMIN')") // 示例:只有ADMIN角色才能访问
public String getAdminData() {
return "This is sensitive admin data.";
}
@GetMapping("/user/info")
@PreAuthorize("hasAuthority('SCOPE_read')") // 示例:拥有read作用域的权限
public String getUserInfo() {
return "User specific information.";
}
}在上述配置中,Spring Security会根据jwk-set-uri(或issuer-uri)自动从Keycloak获取公钥,并在本地验证传入请求中的JWT。这意味着你的微服务无需每次都向Keycloak发起网络请求来验证令牌。
通过实施上述策略,你的微服务架构能够有效应对百万级用户的并发访问,显著降低授权服务的负载,提升整体系统的可伸缩性和响应速度。核心思想是:将令牌验证的负担从授权服务转移到各个资源服务器,利用JWT的自包含特性实现高效的去中心化验证。
以上就是微服务架构下Keycloak授权服务的高效负载处理与JWT验证策略的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号