我使用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中配置一些东西来允许这样做吗?你知道我错过了什么吗?
1条答案
按热度按时间uyto3xhc1#
你的问题缺少了你所有应用的java conf,我们对你的前端和确切的错误日志信息很少,所以很难判断你的问题来自哪里。
您不应该(真的不应该)禁用网关上的CSRF保护:它被配置为OAuth2客户端=>到网关的请求,通过会话保护并暴露于CSRF攻击。
CSRF保护可以在资源服务器(您的“产品”和“资源”服务)上禁用,但只能在那里禁用。
如果前端使用基于JavaScript的框架(Angular,React,Vue等),网关应该配置过滤器,以设置一个CSRF cookie
http-only=false
。