简体   繁体   English

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

[英]spring security permitAll still considering token passed in Authorization header and returns 401 if token is invalid

I am using spring security oauth in my project.我在我的项目中使用 spring security oauth。 I am excluding some urls from authentication by configuring in spring security ResourceServerConfigurerAdapter.我通过在 spring security ResourceServerConfigurerAdapter 中配置从身份验证中排除一些 url。 I added http.authorizeRequests().antMatchers(url).permitAll() .我添加了http.authorizeRequests().antMatchers(url).permitAll()

Now, what I am seeing is that, if I don't pass the Authorization header to these urls, it is not authenticated.现在,我看到的是,如果我不将 Authorization 标头传递给这些 url,则它未通过身份验证。 And the API is called properly.并且 API 被正确调用。

If the call is made with an Authorization header, then it validates the token and fails the call if the token is not validated.如果使用 Authorization 标头进行调用,则它会验证令牌,如果未验证令牌,则调用失败。

My question is what do I need to do so that the token is ignored in the request for which I have permitAll.我的问题是我需要做什么才能在我拥有 permitAll 的请求中忽略令牌。

Spring OAuth2 will intercept all url with header: Authorization Bearer xxx. Spring OAuth2 将拦截所有带有 header: Authorization Bearer xxx 的 url。

To avoid Spring OAuth2 from intercept the url.为了避免 Spring OAuth2 拦截 url。 I have created a SecurityConfiguration which has higher order than Spring OAuth2 configuration.我创建了一个比 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()
    }
}

The above configuration allows /api/public/product/** and /api/public/content/** to be handled by this configuration, not by Spring OAuth2 because this configuration has higher @Order.上述配置允许 /api/public/product/** 和 /api/public/content/** 由该配置处理,而不是由 Spring OAuth2 处理,因为该配置具有更高的@Order。

Therefore, even setting invalid token to above api call will not result in invalid access token.因此,即使将无效令牌设置为上述 api 调用也不会导致访问令牌无效。

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

Note: if your Authorization Server is also a Resource Server then there is another security filter chain with lower priority controlling the API resources.注意:如果您的授权服务器也是资源服务器,那么还有另一个安全过滤器链具有较低的优先级控制 API 资源。 Fo those requests to be protected by access tokens you need their paths not to be matched by the ones in the main user-facing filter chain, so be sure to include a request matcher that picks out only non-API resources in the WebSecurityConfigurer above.对于那些受访问令牌保护的请求,您需要它们的路径不与主要面向用户的过滤器链中的路径相匹配,因此请确保在上面的 WebSecurityConfigurer 中包含一个仅挑选非 API 资源的请求匹配器。

So define WebSecurityConfigurer implementation with higher order than ResourceServerConfig.所以定义 WebSecurityConfigurer 实现比 ResourceServerConfig 更高。

In case you are dealing with Reactive Spring webflux, from SooCheng Koh's answer.如果您正在处理 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();
    }
}

It's not a bug it's a feature:)这不是一个错误,这是一个功能:)

As already mentioned by other people, even if you have permitAll , Spring Security will still check the token if there is a header "Authorization".正如其他人已经提到的,即使您有permitAll ,如果有标头“授权”,Spring Security 仍会检查令牌。 I don't like the workaround on the backend with Order(1) so I did a change on the frontend simply removing the header "Authorization" for the specific request.我不喜欢后端使用Order(1)的解决方法,所以我在前端做了更改,只是删除了特定请求的标头“授权”。 Angular example with interceptor:带有拦截器的角度示例:

@Injectable()
export class PermitAllInterceptor implements HttpInterceptor {
  constructor() {}
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if(req.url.includes('permitAllUrl')){
      req = req.clone({ headers: req.headers.delete('Authorization') });
    }
    return next.handle(req);
  }
}

and then just register the interceptor in app.module.ts:然后在 app.module.ts 中注册拦截器:

{
  provide: HTTP_INTERCEPTORS,
  useClass: PermitAllInterceptor ,
  multi: true
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM