【问题标题】:Oauth2 Resource server overlap Spring Security configurationOauth2 资源服务器重叠 Spring Security 配置
【发布时间】:2017-03-25 12:29:59
【问题描述】:

我正在尝试在 java config 上配置 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();
    }

}

安全配置:

@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 配置与其他配置重叠。我该如何解决?如有任何帮助,我将不胜感激。

【问题讨论】:

    标签: java spring spring-security oauth


    【解决方案1】:

    我看到您想用访问令牌保护一些端点,而用普通表单登录保护其他端点。

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

    【讨论】:

    • 嗨@sofiaguyang,感谢您提出一个想法。我已经限制了ResourceServerConfigurationSecurityConfig 的适用性。现在我看不到错误An Authentication object was not found in the SecurityContext。但是我丢失了一个登录按钮。我不明白我的代码有什么问题。
    • 一般流程是:如果您访问受 OAuth2 保护的端点,您必须提供访问令牌,否则您将收到未经授权/禁止的响应。您可以通过从 /oauth/authorize 检索身份验证代码并将身份验证代码与来自 /oauth/token 的访问令牌交换来获得访问令牌。最初,当用户访问/oauth/authorize 时,用户尚未经过身份验证。但是因为你必须通过身份验证才能授权,所以你会被重定向到登录页面。
    • 谢谢!您对登录按钮有什么想法吗?或者我需要尝试另一种方式来配置 ResourceServer?这是我的配置:http.requestMatcher(new AntPathRequestMatcher("/api/v0/**")).authorizeRequests().antMatchers("/api/v0/**").authenticated().antMatchers("/**").denyAll();
    猜你喜欢
    • 2013-12-21
    • 2017-02-13
    • 2017-03-29
    • 2018-08-17
    • 2019-11-27
    • 2016-01-18
    • 2017-09-13
    • 2017-12-15
    • 2018-07-08
    相关资源
    最近更新 更多