我正在使用 Keycloak 作为身份提供者、Spring Cloud Gateway 作为 API 网关和多个微服务的设置。我可以通过我的网关(重定向到 Keycloak)通过http://localhost:8050/auth/realms/dev/protocol/openid-connect/token
.
我可以使用 JWT 访问直接位于 Keycloak 服务器上的资源(例如http://localhost:8080/auth/admin/realms/dev/users
)。但是当我想使用网关将我中继到相同的资源 ( http://localhost:8050/auth/admin/realms/dev/users
) 时,我会得到 Keycloak 登录表单作为响应。
我的结论是我的 Spring Cloud Gateway 应用程序中一定存在错误配置。
这是网关中的安全配置:
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfiguration {
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http, ReactiveClientRegistrationRepository clientRegistrationRepository) {
// Authenticate through configured OpenID Provider
http.oauth2Login();
// Also logout at the OpenID Connect provider
http.logout(logout -> logout.logoutSuccessHandler(
new OidcClientInitiatedServerLogoutSuccessHandler(clientRegistrationRepository)));
//Exclude /auth from authentication
http.authorizeExchange().pathMatchers("/auth/realms/ahearo/protocol/openid-connect/token").permitAll();
// Require authentication for all requests
http.authorizeExchange().anyExchange().authenticated();
// Allow showing /home within a frame
http.headers().frameOptions().mode(Mode.SAMEORIGIN);
// Disable CSRF in the gateway to prevent conflicts with proxied service CSRF
http.csrf().disable();
return http.build();
}
}
这是我在网关中的 application.yaml:
spring:
application:
name: gw-service
cloud:
gateway:
default-filters:
- TokenRelay
discovery:
locator:
lower-case-service-id: true
enabled: true
routes:
- id: auth
uri: http://localhost:8080
predicates:
- Path=/auth/**
security:
oauth2:
client:
registration:
keycloak:
client-id: 'api-gw'
client-secret: 'not-relevant-but-correct'
authorizationGrantType: authorization_code
redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
scope: openid,profile,email,resource.read
provider:
keycloak:
issuerUri: http://localhost:8080/auth/realms/dev
user-name-attribute: preferred_username
server:
port: 8050
eureka:
client:
service-url:
default-zone: http://localhost:8761/eureka
register-with-eureka: true
fetch-registry: true
如何使网关能够知道用户已通过身份验证(使用 JWT)而不会将我重定向到登录页面?