2015-07-28 6 views
1

Я пытаюсь интегрировать как обычные формы + вход в систему, так и OAuth2 в том же приложении Spring Boot MVC. Возможно, это мое непонимание того, как работает конфигурация Spring Security. Я также попытался адаптировать конфигурацию в примере приложения Sparklr, но я просто не могу это решить.Spring Security Web + OAuth2

Я хотел бы, чтобы любой URL-адрес, соответствующий «/ web/**», был аутентифицирован с регистрацией форм (включая переадресацию на страницу входа), за исключением «resources/**», «/ web/register» и, конечно,/логин» Я также нужна соответствие URL„/ API/**“требовать маркер OAuth2 кроме„/ апи/регистрация“

в настоящее время, кажется, что только ResourceServerConfigurerAdapter принимает эффект. Я пробовал множество комбинаций правил, но я не могу получить эффект, который я хочу. При просмотре вывода отладки я вижу, что он пытается сопоставить конечные точки OAuth, а затем мои конечные точки API, но не какие-либо веб-конечные точки.

Если я получаю регистрацию форм, тогда URL-адреса, которые должны быть защищены 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(); 
     } 
    } 
} 

Вы должны указать antMatcher в вашем ResourceServerConfigurerAdapter HTTP блоке:

@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()); 

} 

Надеется, что это помогает

Смежные вопросы