Oauth2资源服务器重叠Spring Security配置

时间:2016-11-11 09:47:16

标签: java spring spring-security oauth

我正在尝试在java配置上配置Spring Security和OAuth2。我使用的是Spring Security 4.0.4.RELEASE和OAuth2版本2.0.11.RELEASE。

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配置重叠其他配置。我该如何解决?我会感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

我发现您希望使用访问令牌保护某些端点,并使用普通表单登录来保护其他端点。

您是否可以尝试通过以下方式限制ResourceServerConfiguration仅适用于某些端点的适用性:http.requestMatcher(new AntPathRequestMatcher("/api/v0/**"))...。对SecurityConfig执行相同操作,但对于您希望它处理的端点。