OAuth2 Spring Security - OAuth2AuthenticationProcessingFilter 不起作用
Posted
技术标签:
【中文标题】OAuth2 Spring Security - OAuth2AuthenticationProcessingFilter 不起作用【英文标题】:OAuth2 Spring Security - OAuth2AuthenticationProcessingFilter not working 【发布时间】: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();
我的问题是:错误在哪里?
【问题讨论】:
【参考方案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 的顺序后,一切都得到了解决。
干杯
【讨论】:
以上是关于OAuth2 Spring Security - OAuth2AuthenticationProcessingFilter 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
Spring-Security OAuth2 设置 - 无法找到 oauth2 命名空间处理程序
Spring Security OAuth2 v5:NoSuchBeanDefinitionException:'org.springframework.security.oauth2.jwt.Jwt
针对授权标头的Spring Security OAuth2 CORS问题