spring security permitAll 仍在考虑在 Authorization 标头中传递的令牌,如果令牌无效则返回 401

Posted

技术标签:

【中文标题】spring security permitAll 仍在考虑在 Authorization 标头中传递的令牌,如果令牌无效则返回 401【英文标题】:spring security permitAll still considering token passed in Authorization header and returns 401 if token is invalid 【发布时间】:2016-07-17 18:00:40 【问题描述】:

我在我的项目中使用 spring security oauth。我通过在 spring security ResourceServerConfigurerAdapter 中进行配置,从身份验证中排除了一些 url。我加了http.authorizeRequests().antMatchers(url).permitAll()

现在,我看到的是,如果我不将 Authorization 标头传递给这些 url,它就不会经过身份验证。并且 API 被正确调用。

如果使用 Authorization 标头进行调用,则它会验证令牌,如果令牌未被验证,则调用失败。

我的问题是我需要做什么才能在我拥有 permitAll 的请求中忽略令牌。

【问题讨论】:

【参考方案1】:

Spring OAuth2 将拦截所有带有 header: Authorization Bearer xxx 的 url。

为了避免 Spring OAuth2 拦截 url。我创建了一个比 Spring OAuth2 配置更高阶的 SecurityConfiguration。

@Configuration
@EnableWebSecurity
@Order(1) // this is important to run this before Spring OAuth2 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter 

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception 
        return super.authenticationManagerBean();
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        List<RequestMatcher> requestMatchers = new ArrayList<RequestMatcher>();
        // allow /api/public/product/** and /api/public/content/** not intercepted by Spring OAuth2
        requestMatchers.add(new AntPathRequestMatcher("/api/public/product/**"));
        requestMatchers.add(new AntPathRequestMatcher("/api/public/content/**"));

    http
        .requestMatcher(new OrRequestMatcher(requestMatchers))
    .authorizeRequests()
      .antMatchers("/api/public/product/**", "/api/public/content/**").permitAll()
    

以上配置允许 /api/public/product/** 和 /api/public/content/** 由该配置处理,而不是由 Spring OAuth2 处理,因为该配置具有更高的@Order。

因此,即使将无效令牌设置为上述api调用也不会导致无效的访问令牌。

【讨论】:

但是如果token是有效的,你就无法获得认证用户。 @meobeo173 是的,正如你所说,我无法从 auth-server 获取 userInfo。所以,我将user-info-url 端点切换到 api-server。 @meobeo173 我正在使用spring-oauth2spring-boot 设置。但是我创建了 url 以在我的身份验证服务器上获取经过身份验证的用户信息 (security.oauth2.resource.user-info-uri)。在我将我的 spring-security 配置类的顺序更改为1 之前可以,正如这个答案所描述的那样。因此,我将 user-info-uri 端点移到了我的 api-server,它为来自 auth-server 应用程序的休息服务提供服务。【参考方案2】:

根据 spring-oauth2 文档https://projects.spring.io/spring-security-oauth/docs/oauth2.html

注意:如果您的授权服务器也是资源服务器,那么还有另一个具有较低优先级的安全过滤器链来控制 API 资源。对于那些受访问令牌保护的请求,您需要它们的路径不与主要面向用户的过滤器链中的路径匹配,因此请确保在上面的 WebSecurityConfigurer 中包含一个仅挑选非 API 资源的请求匹配器。

所以定义 WebSecurityConfigurer 实现的顺序比 ResourceServerConfig 更高。

【讨论】:

你能详细解释一下粗体字吗?我的意思是,如果有另一个优先级较低的安全过滤器链,为什么它可以控制 API 资源?如果我们为非 API 资源维护一个 WebSecurityConfigurer,那么这些非 API 资源是什么? @hermantvsn【参考方案3】:

如果您正在处理 Reactive Spring webflux,来自 SooCheng Koh 的回答。

@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
@Order(1) // this is important to run this before Spring OAuth2
public class PublicSecurityConfiguration 


    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) 

        http

            .authorizeExchange()
            .pathMatchers("/api/public/**").permitAll();
        return http.build();
    

【讨论】:

以上是关于spring security permitAll 仍在考虑在 Authorization 标头中传递的令牌,如果令牌无效则返回 401的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security Oauth2 permitAll()方法小记

Spring Security permitAll 不适用于某些端点

升级到 Spring Boot 2.0.2 后 Spring Security .permitAll() 不再有效

Spring Security - permitAll() 不允许未经身份验证的访问

PermitAll 在 Spring Security 中不起作用

Spring Security permitAll Unauthorized