2016-11-11 92 views
2

我想在java配置上配置Spring Security和OAuth2。我正在使用Spring Security版本4.0.4.RELEASE和OAuth2版本2.0.11.RELEASE。Oauth2资源服务器重叠Spring安全配置

Spring Security配置工作正常。另外,我可以使用OAuth2 AuthorizationServer获取访问令牌,但是我的ResourceServer无法正常工作。当我设置注释@EnableResourceServer时,我只能检查我无法打开的访问令牌和其他URL(安全配置和授权服务器配置不起作用)。我看到以下错误:

<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?这是我的配置:'http.requestMatcher(new AntPathRequestMatcher(“/ api/v0/**”))。authorizeRequests()。antMatchers(“/ api/v0/**”)。authenticated()。antMatchers(“ **“)denyAll(); ' – Alex

相关问题