问题
I am trying to implement Microservices architecture backend using Spring Boot 1.5.6.RELEASE and Spring Cloud Dalston.SR3 that would be consumed by mobile/web endpoints.
API Gateway application
@SpringBootApplicatio
@EnableEurekaClient
@EnableZuulProxy
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
API security
@Configuration
@EnableWebSecurity
@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)
@EnableOAuth2Sso
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/sign-up", "/login")
.permitAll()
.anyRequest()
.authenticated()
.and()
.csrf()
.ignoringAntMatchers("/sign-up", "/login")
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
// @formatter:on
}
}
Gradle security related dependencies
// Spring OAuth2 security
compile("org.springframework.boot:spring-boot-starter-security")
compile("org.springframework.security.oauth:spring-security-oauth2")
compile("org.springframework.cloud:spring-cloud-starter-oauth2")
compile("org.springframework.security:spring-security-jwt")
Zuul routes
zuul:
ignoredServices: '*'
routes:
user-service:
path: /user-service/**
stripPrefix: false
serviceId: user-webservice
sensitiveHeaders:
task-service:
path: /task-service/**
stripPrefix: false
serviceId: task-webservice
sensitiveHeaders:
user:
path: /userauth/**
stripPrefix: false
serviceId: auth-server
sensitiveHeaders:
I am able to get the access token from the authorization server(stateless sessions - no JSESSIONID cookie)
curl -D - --request POST -u acme:acmesecret "http://localhost:8899/userauth/oauth/token?grant_type=password&username=<...>&password=<...>"
{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MDQ3ODg4NzgsInVzZXJfbmFtZSI6IjcyMTk2MTk2NDEiLCJhdXRob3JpdGllcyI6WyJST0xFX1BBVElFTlQiXSwianRpIjoiZThhMzBjNmQtZjA2MS00MWEzLWEyZGItYTZiN2ZjYTI5ODk1IiwiY2xpZW50X2lkIjoiYWNtZSIsInNjb3BlIjpbIm9wZW5pZCJdfQ.AhF_kqfsRYM1t1HVT........
I can use the access token to request data from the authorization server or another resource
curl -D - --request GET -H "Authorization: Bearer eyJhbGciOiJSUzI1...." http://localhost:8899/userauth/me
{"authorities":[{"authority":"ROLE_P.........}
curl -D - --request GET -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5......." http://localhost:8081/user-service/
[{"firstName":"Anil".....}]
However for the same requests routed through the API gateway, it fails at the Gateway itself and is filtered as AnonymousAuthenticationToken.
curl -D - --request GET -H "Authorization: Bearer eyJhbGciOiJSUzI1...." http://localhost:8765/user-service/
HTTP/1.1 302 Set-Cookie: XSRF-TOKEN=b5a1c34e-e83c-47ea-86a6-13a237c027d4; Path=/ Location: http://localhost:8765/login
I was assuming that with @EnableZuulProxy
and @EnableOAuth2Sso
, Zuul would take care to forward the bearer token to the downstream services but that is not happening. I already have a working sample that uses HTTP session and browser redirection to get the API gateway to pass tokens - https://github.com/anilallewar/microservices-basics-spring-boot
But I am struggling to get it to work with Stateless sessions, any pointers what might be missing on the Zuul API gateway side?
回答1:
Zuul considers Authorization header as a sensitive header by default and does not pass it to downstream requests. To override this, you can modify sensitiveHeaders
in Zuul configuration either globally (for all routes):
zuul:
# exclude Authorization from sensitive headers
sensitiveHeaders: Cookie,Set-Cookie
ignoredServices: '*'
Or for a specific route:
zuul:
ignoredServices: '*'
routes:
user-service:
path: /user-service/**
stripPrefix: false
serviceId: user-webservice
# exclude Authorization from sensitive headers
sensitiveHeaders: Cookie,Set-Cookie
To find more about the problem, check this question:
Authorization header not passed by ZuulProxy starting with Brixton.RC1
回答2:
I was assuming that with @EnableZuulProxy and @EnableOAuth2Sso, Zuul would take care to forward the bearer token to the downstream services but that is not happening.
I assumed the same thing, but in my (painful) experience, @EnableOAuth2Sso secures all endpoints with SSO and blocks even the requests with a Bearer token from getting to downstream services. I had to change my gateway to disable authentication on the routes that lead to my resources, so that the request with a Bearer token could get through.
Try adding /user-service/**
and /task-service/**
to your permitAll()
matcher:
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/sign-up", "/login", "/task-service/**", "/user-service/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.csrf()
.ignoringAntMatchers("/sign-up", "/login")
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
// @formatter:on
}
来源:https://stackoverflow.com/questions/46097559/spring-cloud-zuul-api-gateway-doesnt-forward-jwt-token-for-stateless-sessions