【问题标题】:OAuth2 Spring Security - OAuth2AuthenticationProcessingFilter not workingOAuth2 Spring Security - OAuth2AuthenticationProcessingFilter 不起作用
【发布时间】:2014-07-27 22:44:30
【问题描述】:

嘿,我正在使用 OAuth2 实现 Spring 应用程序。

根据spring documentation,为了启用具有 OAuth2 授权的资源请求,我需要添加 @EnableResourceServer 注释以包含 OAuth2AuthenticationProcessingFilter。

我添加了这个注释,但不幸的是,在启动时没有在链中调用过滤器。

我可以通过 curl 命令获取访问令牌:

curl -X POST -H "Authorization: Basic **************************" -v -H "Accept: application/json" -d "username=my.user&password=pass&client_id=my.user&client_secret=4e1d635a-7c9d-426b-a942-cc166438f996&grant_type=password&scope=read write" http://localhost:8080/oauth/token

但是资源请求:

curl -v -H "Authorization : Bearer ecfa5bfb-c224-4b4a-abf4-cb4a828c2efb" -H "Accept: application/json" http://localhost:8443/oauth/api/meetings/9

给予:

来自服务器的空回复

到主机 localhost 的连接 #0 保持不变

在我的资源配置下:

@Configuration
@EnableWebSecurity
@ComponentScan("com.springapp.mvc")
@EnableResourceServer
@Order(4)
public class Oauth2ResourcesConfigurationAdapter extends ResourceServerConfigurerAdapter {

@Autowired
private OAuth2AuthenticationEntryPoint oAuth2AuthenticationEntryPoint;

@Autowired
private PreAuthUserDetailsService preAuthUserDetailsService;

@Autowired
private OAuth2AccessDeniedHandler accessDeniedHandler;

@Autowired
private DefaultTokenServices tokenServices;

@Autowired
private TokenStore tokenStore;

@Override
public void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/oauth/api/**")
            .access("#oauth2.hasScope('read') and #oauth2.hasScope('write') and #oauth2.hasAnyRole('ROLE_USER','ROLE_ADMIN')")
            .accessDecisionManager(accessDecisionManager())
            .anyRequest()
            .fullyAuthenticated();
    http
            .anonymous()
            .disable();
    http
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.NEVER);
    http
            .exceptionHandling()
            .accessDeniedHandler(accessDeniedHandler);
    http
            .logout()
            .logoutUrl("/oauth/logout")
            .logoutSuccessHandler(logoutSuccessHandler())
            .invalidateHttpSession(true);
    http
            .requiresChannel()
            .antMatchers("/oauth/api/**")
            .requiresSecure();
    http
            .portMapper()
            .http(8080)
            .mapsTo(8443);
}

@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    resources
            .authenticationManager(getAuthenticationManager())
            .tokenServices(tokenServices)
            .tokenStore(tokenStore);
}

private AuthenticationManager getAuthenticationManager() {
    final OAuth2AuthenticationManager oAuth2AuthenticationManager = new OAuth2AuthenticationManager();
    oAuth2AuthenticationManager.setTokenServices(tokenServices);

    return oAuth2AuthenticationManager;
}

private PreAuthenticatedAuthenticationProvider preAuthAuthenticationProvider() {
    final PreAuthenticatedAuthenticationProvider preAuthAuthenticationProvider = new PreAuthenticatedAuthenticationProvider();
    preAuthAuthenticationProvider.setPreAuthenticatedUserDetailsService(preAuthUserDetailsService);

    return preAuthAuthenticationProvider;
}

private AccessDecisionManager accessDecisionManager() {
    return new UnanimousBased(Arrays.<AccessDecisionVoter>asList(new ScopeVoter(),
                                                                 new AuthenticatedVoter(),
                                                                 new WebExpressionVoter()));
}

private LogoutSuccessHandler logoutSuccessHandler() {
    return new OAuth2SuccessLogoutHandler(tokenStore);
}

static final class OAuth2SuccessLogoutHandler implements LogoutSuccessHandler {

    private final TokenStore tokenStore;

    public OAuth2SuccessLogoutHandler(final TokenStore tokenStore) {
        this.tokenStore = tokenStore;
    }

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
           request.toString();
    }
}

}

我的问题是:错误在哪里?

【问题讨论】:

    标签: spring-mvc spring-security oauth-2.0 spring-security-oauth2


    【解决方案1】:

    您需要检查您的 authenticationManager Bean。然后在 ResourceServer 安全配置中检测包含 Authorization 头或 access_token 请求参数的请求。

    以下是一个有效的配置,希望这会有所帮助

    @Configuration
    @EnableOAuth2Sso
    @EnableWebSecurity
    protected static class ResourceConfiguration extends WebSecurityConfigurerAdapter {
    
        @Value("${sso.url}")
        private String ssoUrl;
    
        @Autowired
        private  RedisConnectionFactory redisConnectionFactory;
    
        @Bean
        protected TokenStore tokenStore() {
            return new RedisTokenStore(redisConnectionFactory);
        }
    
        @Bean
        @Primary
        protected ResourceServerTokenServices tokenServices() {
            DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
            defaultTokenServices.setTokenStore(tokenStore());
            defaultTokenServices.setSupportRefreshToken(true);
    
            return defaultTokenServices;
        }
    
    
        @Override
        @Bean
        public AuthenticationManager authenticationManagerBean() throws Exception {
            OAuth2AuthenticationManager authenticationManager = new OAuth2AuthenticationManager();
            authenticationManager.setTokenServices(tokenServices());
            return authenticationManager;
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {      
            http.requestMatchers()
            .and().authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers(HttpMethod.GET, "/static/**").permitAll()
                .antMatchers(HttpMethod.GET, "/profile/**").permitAll()
                .antMatchers(HttpMethod.GET, "/services/**").permitAll()
                .anyRequest().authenticated()
            .and().logout()
                    .invalidateHttpSession(true)
                    .logoutSuccessUrl(ssoUrl+"/logout")
                    .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                    .deleteCookies("JSESSIONID").invalidateHttpSession(true)
                    .permitAll();
        }
    
    }
    
    @Configuration
    @EnableResourceServer
    @Order(1)
    protected static class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    
    
    
        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            resources.resourceId("resource-id");
        }
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.requestMatcher(new OAuthRequestedMatcher())
                .authorizeRequests().anyRequest().fullyAuthenticated();
    
        }
    }
    
    private static class OAuthRequestedMatcher implements RequestMatcher {
        public boolean matches(HttpServletRequest request) {
            String auth = request.getHeader("Authorization");
            boolean haveOauth2Token = (auth != null) && auth.startsWith("Bearer");
            boolean haveAccessToken = request.getParameter("access_token")!=null;
            return haveOauth2Token || haveAccessToken;
        }
    }
    

    【讨论】:

      【解决方案2】:

      好的,下面是给 Spring 初学者的一些建议:

      有一个 FilterChainProxy 类,值得了解它是如何工作的。通常,每个到来的请求都会被标准过滤器和附加过滤器(在配置中添加)过滤。

      每个 WebSecurityConfigurerAdapter 都必须有正确的顺序,并且根据此顺序,您的请求将与正确的请求匹配器绑定。

      请求匹配器提供过滤器来处理您的请求。

      我的问题是,由于 WebAdapters 订购 AnyRequestMatcher 不正确,处理了我的请求,这是不希望的行为。正确的请求匹配器位于更远的位置。

      更改了 WebAdapters 的顺序后,一切都得到了解决。

      干杯

      【讨论】:

        猜你喜欢
        • 2020-10-20
        • 2020-07-17
        • 2018-06-02
        • 2014-08-31
        • 2018-02-05
        • 2018-09-20
        • 1970-01-01
        • 2018-04-22
        • 2019-09-25
        相关资源
        最近更新 更多