2015-07-28 74 views
1

我試圖在同一個Spring Boot MVC應用程序中集成正常形式+會話登錄和OAuth2。這可能是我對Spring Security配置如何工作的誤解。我也嘗試在Sparklr示例應用中修改配置,但我無法解決這個問題。Spring Security Web + OAuth2

我希望任何與「/ web/**」匹配的url可以通過表單登錄(包括重定向到登錄頁面)進行驗證,除了「resources/**」,「/ web/register」以及當然「/login「 我還需要任何匹配」/ api/**「的url來要求除」/ api/register「之外的OAuth2令牌

目前看起來只有ResourceServerConfigurerAdapter正在生效。我嘗試過無數個規則組合,但似乎無法獲得我想要的效果。在查看調試輸出時,我可以看到它試圖匹配OAuth端點,然後匹配我的API端點,但不匹配任何Web端點。

如果我得到表單登錄工作,那麼我需要通過OAuth2加以保護的網址才允許匿名訪問。理解這個/獲得它的任何幫助表示讚賞。

這裏是我的配置:

@Configuration 
@EnableWebSecurity 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
       .authorizeRequests() 
       .antMatchers("/login", "/resources/**", "/web/register").permitAll() 
       //.anyRequest().authenticated() 
       .antMatchers("/web/**").authenticated() 
       .and() 
       .exceptionHandling().accessDeniedPage("/login?authorization_error=true") 
       .and() 
       .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/api/users/register")).disable() 
       .logout().logoutUrl("/logout").logoutSuccessUrl("/login") 
       .and() 
       .formLogin().loginProcessingUrl("/login").failureUrl("/login?authorization_error=true").defaultSuccessUrl("/web/home").loginPage("/login"); 
    } 

    @Autowired 
    private CustomDetailsService userDetailsService; 

    @Autowired 
    private PasswordEncoder passwordEncoder; 

    @Autowired 
    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception { 
       auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder); 
    } 

    @Override 
    @Bean 
    public AuthenticationManager authenticationManagerBean() throws Exception { 
     return super.authenticationManagerBean(); 
    } 
} 

@Configuration 
public class OAuth2ServerConfig { 

    private static final String TEST_RESOURCE_ID = "test"; 

    @Configuration 
    @EnableResourceServer 
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { 

     @Override 
     public void configure(ResourceServerSecurityConfigurer resources) { 
      resources.resourceId(TEST_RESOURCE_ID).stateless(false);    } 

     @Override 
     public void configure(HttpSecurity http) throws Exception { 


      http 
//      Since we want the protected resources to be accessible in the UI as well we need 
//      session creation to be allowed (it's disabled by default in 2.0.6) 
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) 
        .and().authorizeRequests() 
        .antMatchers("/api/users/register").permitAll() 
        .antMatchers("/api/**").access("#oauth2.isOAuth() and hasRole('ROLE_USER')") 
      ; 
     } 
    } 

    @Configuration 
    @EnableAuthorizationServer 
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { 

     @Autowired 
     private TokenStore tokenStore; 

     @Autowired 
     private UserApprovalHandler userApprovalHandler; 

     @Autowired 
     @Qualifier("authenticationManagerBean") 
     private AuthenticationManager authenticationManager; 

     @Autowired 
     private CustomUserDetailsService userDetailsService; 

     @Override 
     public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 
      clients.inMemory().withClient("testapp") 
        .resourceIds(TEST_RESOURCE_ID) 
        .authorizedGrantTypes("authorization_code", "refresh_token", 
          "password") 
        .authorities("USER") 
        .scopes("read", "write") 
        .secret("secret"); 
     } 

     @Bean 
     public TokenStore tokenStore() { 
      return new InMemoryTokenStore(); 
     } 

     @Override 
     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 
      endpoints 
        .tokenStore(tokenStore) 
        .userApprovalHandler(userApprovalHandler) 
        .authenticationManager(authenticationManager) 
        .userDetailsService(userDetailsService); 
     } 

     @Bean 
     @Primary 
     public DefaultTokenServices tokenServices() { 
      DefaultTokenServices tokenServices = new DefaultTokenServices(); 
      tokenServices.setSupportRefreshToken(true); 
      tokenServices.setTokenStore(this.tokenStore); 
      return tokenServices; 
     } 
     @Override 
     public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { 
      oauthServer.realm("test/client"); 
     } 
    } 

    protected static class Approvals { 

     @Autowired 
     private ClientDetailsService clientDetailsService; 

     @Autowired 
     private TokenStore tokenStore; 

     @Bean 
     public ApprovalStore approvalStore() throws Exception { 
      TokenApprovalStore store = new TokenApprovalStore(); 
      store.setTokenStore(tokenStore); 
      return store; 
     } 

     @Bean 
     @Lazy 
     @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) 
     public CustomUserApprovalHandler userApprovalHandler() throws Exception { 
      CustomUserApprovalHandler handler = new CustomUserApprovalHandler(); 
      handler.setApprovalStore(approvalStore()); 
      handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); 
      handler.setClientDetailsService(clientDetailsService); 
      handler.setUseApprovalStore(true); 
      return handler; 
     } 
    } 
} 

回答

0

Multiple HttpSecurity

創建WebSecurityConfigurerAdapter的另一個實例。如果URL不以/ api開頭,則將使用此配置。這個配置在ApiWebSecurityConfigurationAdapter之後被考慮,因爲它的@Order值在1之後(沒有@Order默認爲最後一個值)。

@EnableWebSecurity 
public class MultiHttpSecurityConfig { 
    @Autowired 
    public void configureGlobal(AuthenticationManagerBuilder auth) { 
     auth 
      .inMemoryAuthentication() 
       .withUser("user").password("password").roles("USER").and() 
       .withUser("admin").password("password").roles("USER", "ADMIN"); 
    } 

    @Configuration 
    @Order(1)               
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter { 
     protected void configure(HttpSecurity http) throws Exception { 
      http 
       .antMatcher("/api/**")        
       .authorizeRequests() 
        .anyRequest().hasRole("ADMIN") 
        .and() 
       .httpBasic(); 
     } 
    } 

    @Configuration             
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { 

     @Override 
     protected void configure(HttpSecurity http) throws Exception { 
      http 
       .authorizeRequests() 
        .anyRequest().authenticated() 
        .and() 
       .formLogin(); 
     } 
    } 
} 

你應該在你ResourceServerConfigurerAdapter HTTP塊指定antMatcher

@Override 
public void configure(HttpSecurity http) throws Exception { 
    http.sessionManagement(). 
      sessionCreationPolicy(SessionCreationPolicy.STATELESS); 
    http.antMatcher("/api/**").authorizeRequests() 
      .antMatchers("/api/register").permitAll() 

      ...... 

      .expressionHandler(webExpressionHandler()); 
    http.csrf().disable(); 
    http.exceptionHandling().authenticationEntryPoint(new OAuth2AuthenticationEntryPoint()); 

} 

希望它可以幫助

相關問題