【问题标题】:Spring Security OAuth2 - @EnableOauth2Sso but accept tokens as authentication, tooSpring Security OAuth2 - @EnableOauth2Sso 但也接受令牌作为身份验证
【发布时间】:2017-09-15 17:05:28
【问题描述】:

我有一个在WebSecurityConfigurerAdapter 上有@EnableOAuth2Sso 的应用程序

添加@EnableOAuth2Sso后,应用程序将我重定向到授权服务器,并允许在此授权服务器上登录后访问。我也想提供 API 访问权限,所以我希望应用程序能够通过 Authorization-Header 传递访问令牌来访问我的资源

Authorization: bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... 

我通过与@EnableOAuth2Sso 一起使用的身份验证过滤器进行调试,注意到未检查 Authorization-Header 值。

之后我尝试创建一个自定义过滤器并将这个过滤器添加到安全配置中

@Override
public void configure(HttpSecurity http) throws Exception {
  http.addFilter(myCustomFilter)
    ...;
}

但现在我得到以下异常:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
    ... 26 more
Caused by: org.springframework.security.config.annotation.AlreadyBuiltException: This object has already been built
    at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:44)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.springSecurityFilterChain(WebSecurityConfiguration.java:105)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$f0788cea.CGLIB$springSecurityFilterChain$5(<generated>)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$f0788cea$$FastClassBySpringCGLIB$$7e95689d.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:318)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration$$EnhancerBySpringCGLIB$$f0788cea.springSecurityFilterChain(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)

起初我以为我在过滤器中做错了什么,但我最终得到了一个普通的过滤器类,除了继续过滤器链并仍然有同样的错误。

所以我有两个问题:

  1. 为什么会出现此异常?
  2. 有没有办法允许在使用@EnableOAuth2Sso 的应用程序中对端点进行令牌身份验证?

【问题讨论】:

  • 我猜你的意思是 @EnableOAuth2Sso 而不是 @EnableSso ?您能否详细说明“重定向工作正常”和“也带有不记名令牌的授权标头”
  • 是的,你是对的。我修正了错别字并试图更好地解释我想要实现的目标。

标签: java spring spring-security spring-boot spring-security-oauth2


【解决方案1】:

异常的原因是像@jah说的过滤器的顺序。

为了实现请求的身份验证(在 Authorization-Header 中包含访问令牌),我创建了一个扩展 OAuth2AuthenticationProcessingFilter 的类 ApiTokenAccessFilter。此过滤器采用 ResourceServerTokenServices 构造函数参数并将无状态标志设置为 false。

public class ApiTokenAccessFilter extends OAuth2AuthenticationProcessingFilter {

  public ApiTokenAccessFilter(ResourceServerTokenServices resourceServerTokenServices) {

    super();
    setStateless(false);
    setAuthenticationManager(oauthAuthenticationManager(resourceServerTokenServices));
  }

  private AuthenticationManager oauthAuthenticationManager(ResourceServerTokenServices tokenServices) {

    OAuth2AuthenticationManager oauthAuthenticationManager = new OAuth2AuthenticationManager();

    oauthAuthenticationManager.setResourceId("oauth2-resource");
    oauthAuthenticationManager.setTokenServices(tokenServices);
    oauthAuthenticationManager.setClientDetailsService(null);

    return oauthAuthenticationManager;
  }
}

在我的安全配置中,我使用了这个过滤器,如下所示:

@Configuration
@EnableOAuth2Sso
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Autowired
  private ResourceServerTokenServices tokenServices;

  @Override
  public void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
        .anyRequest()
        .authenticated()
        .and()
        .addFilterBefore(new ApiTokenAccessFilter(tokenServices), AbstractPreAuthenticatedProcessingFilter.class);
  }
}

我认为这可能更容易,所以我在spring-security-oauth Github repo 上打开了一个问题。我不确定这个解决方案是否可行,但我没有找到另一种选择。

【讨论】:

    【解决方案2】:

    这是您第一个问题的答案。您收到此异常是因为您尝试在未指定顺序的情况下将过滤器添加到文件管理器链。 过滤器链由fixed order 中的几个过滤器组成。在要添加的过滤器的check for the existence 中抛出异常。 AbstractSecurityBuilder 中的 org.springframework.security.config.annotation.AlreadyBuiltException 当其中发生异常时。因此,AbstractSecurityBuilder 内部发生的各种异常都导致了这个不相关的异常。

    添加过滤器的一种可能方法是使用 addFilterBefore(Filter filter, Class&lt;? extends Filter&gt; beforeFilter)HttpSecurityaddFilterAfter(Filter filter, Class&lt;? extends Filter&gt; afterFilter) 方法。

    关于您的第二个问题,您应该提供更多信息。

    【讨论】:

    • 我会根据您的回答尝试一些事情。如果可行,我将提供完整的解决方案并将您的答案标记为正确。我明天做
    • 感谢有关过滤器排序的提示。让我更接近解决方案。为此 +1
    猜你喜欢
    • 2021-05-12
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 2017-07-10
    • 2013-06-12
    • 2019-01-28
    • 2015-04-27
    • 2015-08-23
    相关资源
    最近更新 更多