2016-11-11 32 views
2

Javaの設定でSpring SecurityとOAuth2を設定しようとしています。私はSpring Securityバージョン4.0.4.RELEASEとOAuth2バージョン2.0.11.RELEASEを使用しています。Oauth2リソースサーバーがSpring Securityの設定と重複しています

スプリングセキュリティの設定がうまく機能します。また、OAuth2 AuthorizationServerでアクセストークンを取得できますが、ResourceServerが正しく動作しません。注釈@EnableResourceServerを設定すると、自分のアクセストークン、および開くことができない他のURL(セキュリティ設定とAuthorizationServer設定が機能しない)だけをチェックできます。次のエラーが表示されます。

<oauth> 
    <error_description> 
    An Authentication object was not found in the SecurityContext 
    </error_description> 
    <error>unauthorized</error> 
</oauth> 

注釈@EnableResourceServerを削除すると、私のResourceServerはアクセストークンをチェックしません。認証ページにリダイレクトされます。

これは私のコードです:

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true) 
public class GlobalSecurityConfig extends GlobalMethodSecurityConfiguration { 

    @Bean(name = "passwordEncoder") 
    public PasswordEncoder passwordEncoder() { 
     return new BCryptPasswordEncoder(); 
    } 


    @Autowired 
    @Qualifier("authUserDetailsService") 
    private UserDetailsService userDetailsService; 

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

    @Autowired 
    @Qualifier("permissionEvaluator") 
    private PermissionEvaluator permissionEvaluator; 


    @Bean 
    public DefaultMethodSecurityExpressionHandler expressionHandler() { 
     DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler(); 
     handler.setDefaultRolePrefix(""); 
     handler.setPermissionEvaluator(permissionEvaluator); 
     return handler; 
    } 

    @Override 
    protected MethodSecurityExpressionHandler createExpressionHandler() { 
     return expressionHandler(); 
    } 

} 

SecurityConfig:

@Configuration 
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Bean(name = "clientAuthenticationEntryPoint") 
    public OAuth2AuthenticationEntryPoint oauthAuthenticationEntryPoint() { 
     OAuth2AuthenticationEntryPoint entry = new OAuth2AuthenticationEntryPoint(); 
     entry.setRealmName("myapp/client"); 
     entry.setTypeName("Basic"); 
     return entry; 
    } 

    @Autowired 
    @Qualifier("webExpressionHandler") 
    private DefaultWebSecurityExpressionHandler expressionHandler; 


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

    @Bean 
    public SessionRegistry sessionRegistry() { 
     return new SessionRegistryImpl(); 
    } 

    @Override 
    public void configure(WebSecurity web) throws Exception { 
     web.ignoring() 
       .antMatchers("/html/**", "/webapi/**"); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
       .requestMatchers().antMatchers("/admin/**", "/**") 
       .and() 

       .authorizeRequests() 

       .expressionHandler(expressionHandler) 

       .antMatchers("/admin/**").access("hasRole('ADMINISTRATOR')") 
       .antMatchers("/1/admin/**").access("hasRole('ADMINISTRATOR')") 
       .antMatchers("/profile**").authenticated() 
       .antMatchers("/oauth/authorize").authenticated() 
       .and() 
       .formLogin().loginPage("/login") 
       .failureUrl("/login?error=1") 
       .loginProcessingUrl("/login-attempt") 
       .defaultSuccessUrl("/", false) 
       .and() 
       .sessionManagement() 
       .sessionFixation().migrateSession() 
       .and() 

       .logout() 
       .logoutUrl("/logout") 
       .logoutSuccessUrl("/") 

       .and() 
       .exceptionHandling() 
       .accessDeniedPage("/access-denied") 
       .and() 
       .csrf(); 
    } 
} 

のOAuth設定:だから

@Configuration 
public class Oauth { 

    @Configuration 
    @EnableResourceServer 
    public static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { 

     private static final String RESOURCE_ID = "my_oauth_server"; 

     @Override 
     public void configure(ResourceServerSecurityConfigurer resources) throws Exception { 
      resources.resourceId(RESOURCE_ID); 
     } 

     @Override 
     public void configure(HttpSecurity http) throws Exception { 
      http 
        .anonymous().disable() 
        .sessionManagement() 
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
        .and() 
        .authorizeRequests() 

        .regexMatchers("/api/v0/.*").authenticated() 
        .antMatchers("/**").denyAll() 
      ; 

     } 
    } 

    @Configuration 
    @EnableAuthorizationServer 
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { 
     @Autowired 
     private AuthenticationManager authenticationManager; 

     @Autowired 
     private AuthorizationCodeServices verificationCodeService; 

     @Autowired 
     @Qualifier("clientDetails") 
     private ClientDetailsService clientDetailsService; 

     @Autowired 
     @Qualifier("tokenStore") 
     private TokenStore tokenStore; 

     @Bean(name = "tokenServices") 
     public DefaultTokenServices tokenServices() { 
      DefaultTokenServices tokenServices = new DefaultTokenServices(); 
      tokenServices.setTokenStore(tokenStore); 
      tokenServices.setSupportRefreshToken(true); 
      tokenServices.setClientDetailsService(clientDetailsService); 
      return tokenServices; 
     } 

     @Bean 
     public ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter() throws Exception { 
      ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter(); 
      filter.setAuthenticationManager(authenticationManager); 
      return filter; 
     } 

     @Override 
     public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 
      clients.withClientDetails(clientDetailsService); 
     } 

     @Override 
     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 
      endpoints.authenticationManager(authenticationManager); 
      endpoints.authorizationCodeServices(verificationCodeService); 
      endpoints.tokenServices(tokenServices()); 
      endpoints.reuseRefreshTokens(true); 
     } 


     @Override 
     public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { 
      oauthServer.tokenKeyAccess("permitAll()"); 
      oauthServer.checkTokenAccess("permitAll()"); 
      oauthServer.realm("myapp/client"); 
      oauthServer.addTokenEndpointAuthenticationFilter(clientCredentialsTokenEndpointFilter()); 
      oauthServer.allowFormAuthenticationForClients(); 
     } 
    } 
} 

、ResourceServerの設定は、他の構成が重複しています。どうすれば修正できますか?私はどんな助けでも感謝しています。

答えて

0

通常のフォームログインのアクセストークンと他のエンドポイントでいくつかのエンドポイントを保護したいと思っています。

ResourceServerConfigurationの適用範囲を、特定のエンドポイントにのみ適用するように制限することを試みることができますか:http.requestMatcher(new AntPathRequestMatcher("/api/v0/**"))...SecurityConfigでも同じことをしますが、エンドポイントの場合はそれを処理します。

+0

こんにちは@sofiaguyang、アイデア来ていただきありがとうございます。私は 'ResourceServerConfiguration'と' SecurityConfig'の適用範囲を制限しました。今度は、「認証オブジェクトがSecurityContextに見つかりませんでした」というエラーは表示されません。しかし、私はログインボタンを紛失しました。私は自分のコードで何が問題なのか分かりません。 – Alex

+0

一般的な流れは次のとおりです。OAuth2経由で保護されているエンドポイントにアクセスする場合、アクセストークンを提供する必要があります。そうしないと、許可されていない/禁止された応答が送信されます。アクセストークンは、/ oauth/authorizeから認証コードを取得し、認証コードを '/ oauth/token'のアクセストークンと交換することで得られます。最初に、ユーザが '/ oauth/authorize'にアクセスすると、ユーザはまだ認証されていません。しかし、認証するために認証する必要があるため、ログインページにリダイレクトされます。 – sofiaguyang

+0

ありがとう!ログインボタンについて考えていますか?または、別の方法でResourceServerを構成する必要がありますか? antMatchers( "/ api/v0/**")。authenticated()。antMatchers( "/ api/v0/**")。これは私の設定です:http.requestMatcher(新しいAntPathRequestMatcher( " ** "))。denyAll(); ' – Alex

関連する問題