私はモバイル/ Webアプリケーションで消費されるSpring Cloud Dalston.SR4を使用してマイクロサービスアーキテクチャのバックエンドAPIサーバーを実装しようとしています。Spring Cloud Zuul - 生成されたjwtトークンを使用すると認証サーバーからアクセスが拒否されました
APIゲートウェイ以下
はゲートウェイマイクロサービスの構成である
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}
@Configuration
@EnableWebSecurity
@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)
@EnableOAuth2Sso
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() //
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) //
.and().authorizeRequests() //
.antMatchers("/login", "/uaa/**").permitAll() //
.anyRequest().authenticated();
}
}
application.yml
zuul:
ignoredServices: '*'
routes:
user-service:
path: /users/**
service-id: user-service
sensitive-headers:
uaa:
path: /uaa/**
strip-prefix: false
url: ${auth-server.uri}/
sensitive-headers:
security:
user:
password: none
basic:
enabled: false
oauth2:
client:
client-id: client
client-secret: secret
scope: openid
access-token-uri: ${auth-server.uri}/uaa/oauth/token
user-authorization-uri: ${auth-server.uri}/uaa/oauth/authorize
resource:
jwt:
key-value: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhVny3DfQqdvQaPj6SJiiFfPRGH/5k3OiAXTCsmpKnL/GVKZpfFjT3LhN7xoj0DzJLTCOE94eOjIHipFzxrL00kBCZJ3HOornKDpTh17yPuqJI6DNmvJaRBbc3SVQsO0vndnDAeOBiv4euGHH97sPZYFqhmwM35PboqxeWaHrfgWcA5F8VFTp+HDPr26G4sv/UqkR1LsfRoD4gzNJswi00eWcNjeoEzy71023VECQYDytUg/wVqWOJnShWOJnCBnuzmjrtOCg6O6ecdHhVaiRI0//ZR71x2oDW5pe+kgVhhM29TH8SVRjbAFh35obN6ppcF3A7PFLf+euZTsmXMaahQIDAQAB
-----END PUBLIC KEY-----
認証-サービス
@SpringBootApplication
@RestController
@EnableEurekaClient
@EnableResourceServer
public class AuthServiceApplication {
public static void main(String[] args) {
SpringApplication.run(AuthServiceApplication.class, args);
}
@GetMapping("/user")
public Principal getUser(Principal user) {
return user;
}
}
@Configuration
@EnableAuthorizationServer
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"), "keypass".toCharArray());
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setKeyPair(keyStoreKeyFactory.getKeyPair("keystore"));
return converter;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory() //
.withClient("client") //
.secret("secret") //
.authorizedGrantTypes("authorization_code", "refresh_token", "password") //
.scopes("openid") //
.accessTokenValiditySeconds(60 * 60 * 24 * 1);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager).accessTokenConverter(jwtAccessTokenConverter());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
}
@Configuration
@Order(-20)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().disable()//
.csrf().disable() //
.requestMatchers().antMatchers("/login", "/oauth/authorize", "/oauth/confirm_access") //
.and().authorizeRequests().anyRequest().authenticated();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user1").password("pass1").roles("USER");
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
この設定では、uaa/oauth/tokenサービスからアクセストークンを生成できます。そして私はuaa/userサービスのエンドポイントを呼び出すために同じトークンを使用することができ、他のマイクロサービス(user-service)を直接呼び出している間でさえも使用できます。
しかし、以前に生成されたトークンを使用してゲートウェイ経由でユーザーサービスを呼び出すと、認証サーバーからのアクセス拒否エラーが発生します。
要求 - ヘッダ認証をhttp://localhost:8080/users/test
を:ベアラ>
<しかし、認証サーバーからの応答が、アクセスがEnableOAuth2Sso @
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.security.web.FilterChainProxy : /oauth/authorize?client_id=client&redirect_uri=http://localhost:8080/login&response_type=code&scope=openid&state=6AYJ3I at position 5 of 10 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.s.w.s.DefaultSavedRequest : pathInfo: both null (property equals)
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.s.w.s.DefaultSavedRequest : queryString: arg1=client_id=client&redirect_uri=http://localhost:8080/login&response_type=code&scope=openid&state=GwhNJf; arg2=client_id=client&redirect_uri=http://localhost:8080/login&response_type=code&scope=openid&state=6AYJ3I (property not equals)
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.s.w.s.HttpSessionRequestCache : saved request doesn't match
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.security.web.FilterChainProxy : /oauth/authorize?client_id=client&redirect_uri=http://localhost:8080/login&response_type=code&scope=openid&state=6AYJ3I at position 6 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.security.web.FilterChainProxy : /oauth/authorize?client_id=client&redirect_uri=http://localhost:8080/login&response_type=code&scope=openid&state=6AYJ3I at position 7 of 10 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.s.w.a.AnonymousAuthenticationFilter : Populated SecurityContextHolder with anonymous token: 'org.sprin[email protected]905571d8: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]0: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 0F2BD608483668F10E9AD88B507858E9; Granted Authorities: ROLE_ANONYMOUS'
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.security.web.FilterChainProxy : /oauth/authorize?client_id=client&redirect_uri=http://localhost:8080/login&response_type=code&scope=openid&state=6AYJ3I at position 8 of 10 in additional filter chain; firing Filter: 'SessionManagementFilter'
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.security.web.FilterChainProxy : /oauth/authorize?client_id=client&redirect_uri=http://localhost:8080/login&response_type=code&scope=openid&state=6AYJ3I at position 9 of 10 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.security.web.FilterChainProxy : /oauth/authorize?client_id=client&redirect_uri=http://localhost:8080/login&response_type=code&scope=openid&state=6AYJ3I at position 10 of 10 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /oauth/authorize?client_id=client&redirect_uri=http://localhost:8080/login&response_type=code&scope=openid&state=6AYJ3I; Attributes: [authenticated]
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.sprin[email protected]905571d8: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]0: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 0F2BD608483668F10E9AD88B507858E9; Granted Authorities: ROLE_ANONYMOUS
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.s.access.vote.AffirmativeBased : Voter: org.sp[email protected]21c53585, returned: -1
2017-10-23 12:38:41.470 DEBUG 4320 --- [trace=,span=] [nio-9999-exec-4] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)