我正在开发一个 Spring Boot 微服务项目,该项目使用 oauth2,遵循使用 Keycloak 进行身份验证的 YouTube 教程。我没有使用 Keycloak,而是选择通过添加从 Google 开发者控制台获取的 Google Client ID 和 Secret ID 将 Google OAuth2 配置为身份验证机制。
尽管如此配置,我仍然遇到问题。我的预期结果是通过 API 网关成功进行服务调用,这应该提示 Google 登录页面进行身份验证。成功登录后,我希望被重定向回我定义的端点。
SecurityConfig.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity serverHttpSecurity, ReactiveClientRegistrationRepository clientRegistrationRepository) {
serverHttpSecurity
.csrf(ServerHttpSecurity.CsrfSpec::disable)
.authorizeExchange(exchange ->
exchange.pathMatchers("/eureka/**")
.permitAll()
.anyExchange()
.authenticated())
.oauth2Login(oauth2 -> oauth2
.clientRegistrationRepository(clientRegistrationRepository));
return serverHttpSecurity.build();
}
}
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<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-oauth2-client</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-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
应用程序属性
spring.application.name=api-gateway
eureka.client.serviceUrl.defaultZone=http://eureka:password@localhost:8761/eureka
app.eureka-server=localhost
## Product Service Route
spring.cloud.gateway.routes[0].id=product-service
spring.cloud.gateway.routes[0].uri=lb://product-service
spring.cloud.gateway.routes[0].predicates[0]=Path=/api/product
## Order Service Route
spring.cloud.gateway.routes[1].id=order-service
spring.cloud.gateway.routes[1].uri=lb://order-service
spring.cloud.gateway.routes[1].predicates[0]=Path=/api/order
## Discover Server Route
spring.cloud.gateway.routes[2].id=discovery-server
spring.cloud.gateway.routes[2].uri=http://eureka:password@${app.eureka-server}:8761
spring.cloud.gateway.routes[2].predicates[0]=Path=/eureka/web
spring.cloud.gateway.routes[2].filters[0]=SetPath=/
## Discover Server Static Resources Route
spring.cloud.gateway.routes[3].id=discovery-server-static
spring.cloud.gateway.routes[3].uri=http://eureka:password@${app.eureka-server}:8761
spring.cloud.gateway.routes[3].predicates[0]=Path=/eureka/**
#spring.security.oauth2.resourceserver.jwt.issuer-uri= http://localhost:8080/realms/spring-boot-microservices-realm
spring.security.oauth2.client.registration.google.client-id= 186452584986-77gtfh20v3k0thtskoti1akgvgoclhbt.apps.googleusercontent.com
spring.security.oauth2.client.registration.google.client-secret= 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
spring.security.oauth2.client.registration.google.scope=openid,profile,email
server.servlet.session.cookie.same-site=lax
management.zipkin.tracing.endpoint=http://localhost:9411/api/v2/spans
management.tracing.sampling.probability=1.0
# Actuator Prometheus Endpoint
management.endpoints.web.exposure.include= prometheus
server.port=8181
logging.pattern.level=%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]
控制器.java
@RequestMapping
@RestController("/hello")
public class ApiGateWayCtrl {
@GetMapping("/wow")
public String get(){
return "hello world!";
}
}
当我呼叫端点时,它会直接打开谷歌提示进行登录,但在我使用我的帐户登录后,而不是将我重定向到端点,它基本上显示此消息
在浏览器控制台中,它显示对端点和 google 的调用的代码 302。 您能否提供有关如何使用 Google OAuth2 正确实施此流程的指导? 我对 webflux 的安全性还很陌生,所以如果我的方法是错误的,我愿意听听你的想法
谢谢你。
不要直接使用 Google 作为 OpenID 提供商,这会阻止您:
相反,请使用您自己的 Google OIDC 提供商作为其身份源。 Keycloak 可以做到这一点,就像大多数其他 OIDC 提供商(Auth0、Okta、Amazon Cognito 等)一样。
我写了您可能应该阅读的教程:
由于您是 OAuth2 的新手,因此从 Keycloak 教程开始并特别注意提供一些 OAuth2 背景的部分非常重要。