oauth2.0 尝试使用Keycloak发出POST请求,说CSRF令牌丢失

aamkag61  于 2023-08-02  发布在  其他
关注(0)|答案(1)|浏览(133)

我使用docker-compose文件设置了一个Keycloak服务器:

auth-db:
    image: postgres:13.5
    environment:
        POSTGRES_HOST_AUTH_METHOD: trust
        POSTGRES_USER: my_admin
        POSTGRES_PASSWORd: my_password
        POSTGRES_DB: keycloak_db
    ports:
        - '5432:5432'
  keycloak:
   image: quay.io/keycloak/keycloak:legacy
   environment:
     DB_VENDOR: POSTGRES
     DB_ADDR: auth-db

     DB_SCHEMA: public
     DB_DATABASE: keycloak_db
     DB_USER: my_admin
     DB_PASSWORD: my_password
     KEYCLOAK_USER: kc_admin
     KEYCLOAK_PASSWORD: kc_password
   ports:
     - '8080:8080'
   depends_on:
     - auth-db

字符串
我把我的网关连接成这样-

server:
  port: 8082
spring:
  main:
    web-application-type: reactive
  application:
    name: GATEWAY-SERVICE
  cloud:
    gateway:
      routes:
       - id: product-service
         uri: http://product-service:8081/products
         predicates:
           Path=/products/**
         filters:
           TokenRelay=
       - id: resource-service
         uri: http://resource-service:8083/message
         predicates:
           Path=/message/**
         filters:
           TokenRelay=

  security:
    oauth2:
      client:
        registration:
             gateway:
              provider: my-provider
              client-id: my_client
              client-secret: tY0eCQyWnpqPKftcEP0S5T3ZXbETsji3
              authorization-grant-type: authorization_code
              redirect-uri: "http://gateway-service:8082/login/oauth2/code/{registrationId}"
        provider:
          my-provider:
            issuer-uri: http://keycloak:8080/auth/realms/my_realm

eureka:
  client:
    healthcheck:
      enabled: true
    register-with-eureka: true
  instance:
    health-check-url: /health
    hostname: gateway-service
    prefer-ip-address: true
logging:
  level:
    org.springframework.cloud: TRACE
    org.springframework.security: DEBUG


我的产品服务中的过滤器链示例

@EnableWebSecurity
public class SecurityConfig {

    private final RSAPublicKey key;
    private final JwtDecoder jwtDecoder;

    public SecurityConfig(JwtDecoder jwtDecoder, RSAPublicKey key) {
        this.key=key;
        this.jwtDecoder=jwtDecoder;
    }
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http   .csrf(csrf -> csrf.disable())
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("/**")
                        .hasAnyAuthority("SCOPE_message.read, SCOPE_message.write")


                )
                .formLogin(AbstractHttpConfigurer::disable)
                .oauth2ResourceServer((oauth2)-> oauth2.jwt((jwt) ->
                                jwt
                                        .decoder(jwtDecoder())
                        )
                );
        return http.build();
    }

    public JwtDecoder jwtDecoder() {
        return NimbusJwtDecoder.withPublicKey(this.key).build();
    }
}


我的产品-服务的应用程序.yml。

server:
  port: 8081
spring:
  application:
    name: product-service
  datasource:
    url: jdbc:mysql://product-db:3307/PRODUCT_DB
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: user
    password: user

  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://keycloak:8080/auth/realms/my_realm
eureka:
  client:
    register-with-eureka: true
  instance:
    prefer-ip-address: true
    hostname: product-service
logging:
  level:
    org.springframework.security: DEBUG


我的其他微服务被配置为资源服务器,并且能够很好地执行GET请求。但是,如果我在Postman上尝试POST请求,我会收到- 403 Forbidden -“无法找到预期的CSRF令牌”
我已经在我的安全过滤器中为每个微服务禁用了csrf,包括网关。我可以在Keycloak中配置一些东西来允许这样做吗?你知道我错过了什么吗?

uyto3xhc

uyto3xhc1#

你的问题缺少了你所有应用的java conf,我们对你的前端和确切的错误日志信息很少,所以很难判断你的问题来自哪里。
您不应该(真的不应该)禁用网关上的CSRF保护:它被配置为OAuth2客户端=>到网关的请求,通过会话保护并暴露于CSRF攻击。
CSRF保护可以在资源服务器(您的“产品”和“资源”服务)上禁用,但只能在那里禁用。
如果前端使用基于JavaScript的框架(Angular,React,Vue等),网关应该配置过滤器,以设置一个CSRF cookie http-only=false

相关问题