如何配置Spring Cloud Gateway区分API与UI的认证流程
实现Spring Cloud Gateway双认证路由配置(UI OIDC + API JWT)
完全可以实现,核心思路是通过路由路径匹配+多组安全过滤器链,为UI和API路径绑定各自的认证逻辑。以下是具体操作步骤:
1. 依赖准备
确保项目依赖包含Spring Cloud Gateway、OAuth2客户端(用于OIDC登录)、OAuth2资源服务器(用于JWT验证):
<!-- Spring Cloud Gateway --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- OAuth2 Client(OIDC登录用) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> <!-- OAuth2 Resource Server(JWT验证用) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-resource-server</artifactId> </dependency>
2. 配置Keycloak基础参数
在application.yml中配置Keycloak的客户端(UI用)和资源服务器(API用)信息:
spring: security: oauth2: client: registration: keycloak-ui: client-id: <你的UI客户端ID> client-secret: <你的UI客户端密钥> authorization-grant-type: authorization_code redirect-uri: "{baseUrl}/login/oauth2/code/keycloak-ui" scope: openid,profile,email provider: keycloak-ui: issuer-uri: <Keycloak Realm的Issuer地址> user-name-attribute: preferred_username resourceserver: jwt: issuer-uri: <同上Keycloak Realm的Issuer地址>
3. 自定义多组安全过滤器链
通过SecurityWebFilterChain分别为UI、API、公共路径配置独立的认证规则:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler; import org.springframework.security.oauth2.client.oidc.web.server.logout.OidcClientInitiatedServerLogoutSuccessHandler; @Configuration @EnableWebFluxSecurity public class GatewaySecurityConfig { // UI路径的OIDC登录规则 @Bean public SecurityWebFilterChain uiSecurityFilterChain(ServerHttpSecurity http) { http .securityMatcher("/ui/**") // 匹配所有UI前缀路径 .authorizeExchange(exchanges -> exchanges.anyExchange().authenticated()) .oauth2Login(oauth2 -> oauth2 .authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/ui/home")) ) .logout(logout -> logout .logoutSuccessHandler(new OidcClientInitiatedServerLogoutSuccessHandler()) ); return http.build(); } // API路径的JWT资源服务器规则 @Bean public SecurityWebFilterChain apiSecurityFilterChain(ServerHttpSecurity http) { http .securityMatcher("/api/**") // 匹配所有API前缀路径 .authorizeExchange(exchanges -> exchanges.anyExchange().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> {})); return http.build(); } // 公共路径放行规则(比如登录页、静态资源) @Bean public SecurityWebFilterChain publicSecurityFilterChain(ServerHttpSecurity http) { http .securityMatcher("/", "/login", "/static/**") .authorizeExchange(exchanges -> exchanges.anyExchange().permitAll()); return http.build(); } }
4. 配置路由转发规则
在application.yml中定义UI和API的路由,确保路径与安全规则匹配:
spring: cloud: gateway: routes: # UI路由 - id: ui-route uri: lb://ui-service # 替换为你的UI服务地址 predicates: - Path=/ui/** filters: - StripPrefix=1 # 转发时去掉/ui前缀 # API路由 - id: api-route uri: lb://api-service # 替换为你的API服务地址 predicates: - Path=/api/** filters: - StripPrefix=1 # 转发时去掉/api前缀
关键注意事项
- 路径匹配顺序:Spring Cloud Gateway按路由定义顺序匹配,建议把公共路径放在最前面,避免被其他规则拦截。
- JWT自动验证:API路径的JWT验证会自动从Keycloak的Issuer地址获取公钥,无需手动配置密钥。
- 会话与令牌隔离:UI的OIDC会话通过Cookie管理,API的JWT令牌通过请求头(
Authorization: Bearer <token>)传递,两者互不干扰。 - 跨域配置:如果UI和API存在跨域场景,需在Gateway中配置CORS规则,确保OIDC回调和API请求正常。
内容的提问来源于stack exchange,提问作者Emtiaz
相关产品推荐
相关产品推荐

