【问题标题】:spring security - authorize pre-flighted request without oAuth tokenspring security - 在没有 oAuth 令牌的情况下授权预发送请求
【发布时间】:2021-01-30 12:51:03
【问题描述】:

我正在尝试在没有授权标头的情况下授权 (/secure/**) 中的所有预检请求(在我的情况下为 oauth 令牌)。 JwkFilter 用于验证在授权标头中传递的 oauth 令牌。任何建议,我在这里哪里出错了。

@Override
protected void configure(HttpSecurity http) throws Exception {
    
    JwtAuthFilter jwtAuthTokenFilter = new JwtAuthFilter(oauthConfig);
    jwtAuthTokenFilter.setAuthenticationManager(getAuthManager());

    http.cors().and().authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/secure/**")
            .permitAll();

    http.requiresChannel().anyRequest().requiresSecure().and()
            .addFilterBefore(requireProtocolFilter, ChannelProcessingFilter.class).sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().anonymous().disable().csrf().disable()
            .antMatcher("/**").authorizeRequests().anyRequest().permitAll().and()
            .antMatcher(/secure/**")
            .addFilterBefore(jwtAuthTokenFilter, BasicAuthenticationFilter.class).exceptionHandling()
            .authenticationEntryPoint(authenticationEntryPoint()).and().authorizeRequests().anyRequest()
            .authenticated();

}

public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurerAdapter() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                .allowedMethods("*")
                .allowedOrigins("*");
        }
    };
}

【问题讨论】:

    标签: spring-security oauth cors preflight


    【解决方案1】:

    对于带有 CORS 的预检请求,根据 spring,它们将在您的 jwtAuthTokenFilter 之前执行(在 BasicAuthenticationFilter 过滤器之前注册)-> 正确

    这里指定了订单(in spring code):

    FilterComparator() {
            Step order = new Step(INITIAL_ORDER, ORDER_STEP);
            ...
            put(CorsFilter.class, order.next());
            ...
            put(BasicAuthenticationFilter.class, order.next());
            ...
        }
    

    在 CORS 中,对于复杂的请求(例如在您的情况下使用自定义标头 Authorization 标头),浏览器将首先发送预检请求以了解服务器是否允许客户端访问其资源,然后再发送实际请求。

    CORSFilter 将像这样执行 (in spring code):

    public class CorsFilter extends OncePerRequestFilter {
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                FilterChain filterChain) throws ServletException, IOException {
    
            CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request);
            boolean isValid = this.processor.processRequest(corsConfiguration, request, response);
            if (!isValid || CorsUtils.isPreFlightRequest(request)) {
                return;
            }
            filterChain.doFilter(request, response);
        }
    }
    

    他们将检查是否每个预检请求(扩展 OncePerRequestFilter)到达服务器,如果 processRequest 是有效的或者是预检请求以终止链。 这是检查预检请求的默认处理器 (in spring code):

    public class DefaultCorsProcessor implements CorsProcessor {
    
        @Override
        public boolean processRequest(@Nullable CorsConfiguration config, HttpServletRequest request,
                HttpServletResponse response) throws IOException {
    
            ...
            boolean preFlightRequest = CorsUtils.isPreFlightRequest(request);
            if (config == null) {
                if (preFlightRequest) {
                    rejectRequest(new ServletServerHttpResponse(response));
                    return false;
                }
                else {
                    return true;
                }
            }
            return handleInternal(new ServletServerHttpRequest(request), new ServletServerHttpResponse(response), config, preFlightRequest);
        }
    

    就您而言,我认为您缺少启用 CORS 的配置。 所以服务器拒绝客户端请求(通过发送 HttpStatus.FORBIDDEN 代码),这样浏览器就不会向服务器发送实际请求。 而且你的 JwtAuthTokenFilter 没有机会执行。

    你可以参考this post配置cors。希望对你有帮助

    【讨论】:

    • 对不起,我没有提到我在同一个类中定义了 corsConfigurer。我现在已经添加了代码。
    • 我认为您还需要配置用于 securityFilterChain 的 CorsFilter 的 CorsConfigurationSource。这里的 corsConfigurer() 没有任何意义,因为你的请求还没有到达 MVC Handler。流程:securityFilterChain -> MVC 处理程序。而你仍然停留在 securityFilterChain。
    【解决方案2】:

    将下面的 sn-p 添加到 jwkAuthFilter 中就可以了。

         if (CorsUtils.isPreFlightRequest(request)) {
            response.setStatus(HttpServletResponse.SC_OK);
            return;
        }
    

    【讨论】:

      猜你喜欢
      • 2018-06-29
      • 2016-08-29
      • 2011-11-16
      • 1970-01-01
      • 2020-11-03
      • 2022-11-23
      • 2018-06-11
      • 2017-10-16
      • 1970-01-01
      相关资源
      最近更新 更多