使用 WebFlux OAuth2 进行社交登录

问题描述 投票:0回答:1

我正在开发一个 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-oauth microservices spring-webflux
1个回答
0
投票

不要直接使用 Google 作为 OpenID 提供商,这会阻止您:

  • 将数据附加到用户(如角色)
  • 在配置为资源服务器的 REST 服务上使用访问令牌(当前问题的可能原因)
  • 轻松添加更多社交身份来源(Facebook、Github...)

相反,请使用您自己的 Google OIDC 提供商作为其身份源。 Keycloak 可以做到这一点,就像大多数其他 OIDC 提供商(Auth0、Okta、Amazon Cognito 等)一样。

我写了您可能应该阅读的教程:

由于您是 OAuth2 的新手,因此从 Keycloak 教程开始并特别注意提供一些 OAuth2 背景的部分非常重要。

© www.soinside.com 2019 - 2024. All rights reserved.