我有一個彈簧啓動+角度web應用程序,它嚴格遵循此tutorial的設置:我在同一個Spring Boot應用程序中運行授權服務器,資源服務器,UI Web應用程序。無法獲得Spring OAuth SSO過濾器來觸發
然後我有需要允許用戶登錄與第三方社會登錄(Facebook等),並隱式創建用戶帳戶,如果使用尚未註冊以前。
我試圖通過遵循另一個教程here來完成此操作。
在本教程中,使GET /login/facebook
調用會觸發代碼中設置的SSOFilter。但是這並沒有發生在我自己的代碼中。我試圖將SSO過濾器的順序更改爲不同的數字,但它也沒有幫助。
在教程auth-server示例的日誌中。我看到下面的輸出:
2016-09-24 22:59:26.728 DEBUG 59433 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request '/login/facebook' matched by universal pattern '/**'
2016-09-24 22:59:26.728 DEBUG 59433 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-09-24 22:59:26.729 DEBUG 59433 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-09-24 22:59:26.729 DEBUG 59433 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2016-09-24 22:59:26.729 DEBUG 59433 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
2016-09-24 22:59:26.731 DEBUG 59433 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2016-09-24 22:59:26.732 DEBUG 59433 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter'
2016-09-24 22:59:26.736 DEBUG 59433 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
2016-09-24 22:59:26.736 DEBUG 59433 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'GET /login/facebook' doesn't match 'POST /logout
2016-09-24 22:59:26.736 DEBUG 59433 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 6 of 12 in additional filter chain; firing Filter: 'CompositeFilter'
2016-09-24 22:59:26.737 DEBUG 59433 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login/facebook'; against '/login/facebook'
在我自己的日誌中,我沒有看到過CompositeFilter
被觸發:
2016-09-24 23:38:54.545 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request '/login/facebook' matched by universal pattern '/**'
2016-09-24 23:38:54.546 DEBUG 60184 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-09-24 23:38:54.547 DEBUG 60184 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-09-24 23:38:54.547 DEBUG 60184 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2016-09-24 23:38:54.548 DEBUG 60184 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
2016-09-24 23:38:54.548 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', GET]
2016-09-24 23:38:54.548 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login/facebook'; against '/logout'
2016-09-24 23:38:54.548 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', POST]
2016-09-24 23:38:54.548 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'GET /login/facebook' doesn't match 'POST /logout
2016-09-24 23:38:54.548 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', PUT]
2016-09-24 23:38:54.548 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'GET /login/facebook' doesn't match 'PUT /logout
2016-09-24 23:38:54.548 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', DELETE]
2016-09-24 23:38:54.549 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'GET /login/facebook' doesn't match 'DELETE /logout
2016-09-24 23:38:54.549 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.web.util.matcher.OrRequestMatcher : No matches found
2016-09-24 23:38:54.549 DEBUG 60184 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 5 of 11 in additional filter chain; firing Filter: 'OAuth2AuthenticationProcessingFilter'
2016-09-24 23:38:54.549 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.o.p.a.BearerTokenExtractor : Token not found in headers. Trying request parameters.
2016-09-24 23:38:54.549 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.o.p.a.BearerTokenExtractor : Token not found in request parameters. Not an OAuth2 request.
2016-09-24 23:38:54.549 DEBUG 60184 --- [nio-8080-exec-1] p.a.OAuth2AuthenticationProcessingFilter : No token in request, will continue chain.
2016-09-24 23:38:54.549 DEBUG 60184 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2016-09-24 23:38:54.549 DEBUG 60184 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2016-09-24 23:38:54.550 DEBUG 60184 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2016-09-24 23:38:54.551 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter : Populated SecurityContextHolder with anonymous token: 'org.sprin[email protected]9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
2016-09-24 23:38:54.551 DEBUG 60184 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
2016-09-24 23:38:54.552 DEBUG 60184 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2016-09-24 23:38:54.552 DEBUG 60184 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2016-09-24 23:38:54.552 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login/facebook'; against '/api/**'
2016-09-24 23:38:54.552 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Public object - authentication not attempted
2016-09-24 23:38:54.553 DEBUG 60184 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login/facebook reached end of additional filter chain; proceeding with original chain
2016-09-24 23:38:54.571 DEBUG 60184 --- [nio-8080-exec-1] .s.o.p.e.FrameworkEndpointHandlerMapping : Looking up handler method for path /login/facebook
2016-09-24 23:38:54.571 DEBUG 60184 --- [nio-8080-exec-1] .s.o.p.e.FrameworkEndpointHandlerMapping : Did not find handler method for [/login/facebook]
2016-09-24 23:38:54.574 DEBUG 60184 --- [nio-8080-exec-1] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.se[email protected]76f064a2
我拉我的頭髮掉,但仍毫無頭緒出了什麼錯我的代碼。
這是我設置的代碼片段:
主類文件:
@SpringBootApplication
public class TuangouApplication extends SpringBootServletInitializer {
public static void main(String[] args) throws Exception {
SpringApplication.run(TuangouApplication.class, args);
}
// this is for WAR file deployment
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(TuangouApplication.class);
}
@Bean
public javax.validation.Validator localValidatorFactoryBean() {
return new LocalValidatorFactoryBean();
}
}
WebSecurityConfiguration文件。 幾乎與spring oauth2教程auth-server
示例相同。
@Configuration
@EnableOAuth2Client
@Order(6)
public class TuangouConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private OAuth2ClientContext oauth2ClientContext;
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.antMatcher("/**").authorizeRequests().antMatchers("/", "/login**").permitAll()
.and().exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/"))
.and().formLogin().loginPage("/login").failureUrl("/login?error").permitAll()
.and().logout().logoutSuccessUrl("/").permitAll()
.and().csrf().csrfTokenRepository(csrfTokenRepository())
.and().addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
// @formatter:on
}
// @Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true)
protected static class AuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter {
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService()).passwordEncoder(new BCryptPasswordEncoder());
}
@Bean
public UserDetailsService userDetailsService() {
return new DatabaseUserServiceDetails();
}
}
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request
.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null
|| token != null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
@Bean
public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean();
System.out.println("### foobar");
registration.setFilter(filter);
registration.setOrder(-100);
return registration;
}
@Bean
@ConfigurationProperties("github")
public ClientResources github() {
return new ClientResources();
}
@Bean
@ConfigurationProperties("facebook")
public ClientResources facebook() {
return new ClientResources();
}
private Filter ssoFilter() {
CompositeFilter filter = new CompositeFilter();
List<Filter> filters = new ArrayList<Filter>();
filters.add(ssoFilter(facebook(), "/login/facebook"));
filters.add(ssoFilter(github(), "/login/github"));
filter.setFilters(filters);
return filter;
}
private Filter ssoFilter(ClientResources client, String path) {
OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(
path);
OAuth2RestTemplate template = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
filter.setRestTemplate(template);
filter.setTokenServices(new UserInfoTokenServices(
client.getResource().getUserInfoUri(), client.getClient().getClientId()));
return filter;
}
}
class ClientResources {
@NestedConfigurationProperty
private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();
@NestedConfigurationProperty
private ResourceServerProperties resource = new ResourceServerProperties();
public AuthorizationCodeResourceDetails getClient() {
return client;
}
public ResourceServerProperties getResource() {
return resource;
}
}
授權服務器的配置:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager auth;
@Autowired
private DataSource dataSource;
private BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
@Bean
public JdbcTokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Bean
protected AuthorizationCodeServices authorizationCodeServices() {
return new JdbcAuthorizationCodeServices(dataSource);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security)
throws Exception {
security.passwordEncoder(passwordEncoder);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints.authorizationCodeServices(authorizationCodeServices())
.authenticationManager(auth).tokenStore(tokenStore())
.approvalStoreDisabled();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// @formatter:off
clients.jdbc(dataSource).passwordEncoder(passwordEncoder);
// .withClient("grubmarket")
// .authorizedGrantTypes("password", "authorization_code", "client_credentials",
// "refresh_token", "implicit")
// .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
// .scopes("read", "write", "trust")
// .resourceIds("oauth2-resource")
// .accessTokenValiditySeconds(3600);
// @formatter:on
}
}
資源服務器配置:
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter{
@Autowired
private TokenStore tokenStore;
@Override
public void configure(ResourceServerSecurityConfigurer resources)
throws Exception {
resources.tokenStore(tokenStore);
}
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.antMatcher("/**").authorizeRequests().antMatchers("/api/**").permitAll();
// http.antMatcher("/api/**").authorizeRequests().antMatchers(HttpMethod.GET, "/api/deals").permitAll().anyRequest().authenticated();
// @formatter:on
}
}
工作正常!我在哪裏可以找到各種過濾器的默認訂單?當程序運行時,是否可以打印出或記錄所有過濾器的相對順序? –
由'@ EnableResourceServer'創建的Spring安全篩選器鏈的默認順序在javadoc - ...硬編碼Order(of 3)中指定。另外,你可以通過在你的'TuangouConfiguration'中覆蓋以下內容來調試它們各自鏈中過濾器的順序....'public void configure(WebSecurity web)拋出異常{ \t \t web.debug(true); \t} ' –
另一個需要注意的重要配置是'HttpSecurity.antMatcher()'。我注意到你在'TuangouConfiguration'和'ResourceServerConfiguration'中使用了它們,但它們都在'/ **'上匹配。我建議在'ResourceServerConfiguration'上使用更具體的模式,例如'/ api/**'。這也可以,並且當請求是'/ login/facebook'時,你可以調用你的'ssoFilter',並且不需要在你的'TuangouConfiguration'上使用@Order。我強烈建議使用這種配置方法。 –