简体   繁体   English

预检响应中的 Access-Control-Allow-Headers 不允许请求 header 字段 ack 即使服务器已经允许它

[英]Request header field ack is not allowed by Access-Control-Allow-Headers in preflight response even the server already allowing it

I know this question already spreading all over the stackoverflow, but this one quite different.我知道这个问题已经遍布整个 stackoverflow,但这个问题完全不同。

I got an error when trying to hit a java API using axios, with below way,尝试使用 axios 击中 java API 时出现错误,方法如下,

axios
      .get("http://127.0.0.1:8090/api/v1/homescreen")
      .then(response => {
        console.log(response);
      })
      .catch(err => {
        console.log(err);
      });
  }

Axios configuration were Axios配置分别

axios.defaults.headers.common['Content-Type'] = 'application/x-www-form-urlencoded'; axios.defaults.headers.common['Content-Type'] = 'application/x-www-form-urlencoded'; axios.defaults.headers.common['Authorization'] = 'Bearer eyJhbGciOiJIUzI1N'; axios.defaults.headers.common['Authorization'] = '承载 eyJhbGciOiJIUzI1N'; axios.defaults.headers.common['Ack'] = 'MTIwNzIwMjBL=='; axios.defaults.headers.common['Ack'] = 'MTIwNzIwMjBL==';

Already tried with axios.defaults.headers.common['Content-Type'] = application/json;已经尝试使用axios.defaults.headers.common['Content-Type'] = application/json; and got the same error.并得到同样的错误。

The error was错误是

Access to XMLHttpRequest at 'http://127.0.0.1:8090/api/v1/homescreen' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field ack is not allowed by Access-Control-Allow-Headers in preflight response. Access to XMLHttpRequest at 'http://127.0.0.1:8090/api/v1/homescreen' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field ack is not allowed by Access-Control - 预检响应中的允许标头。

Now in the server side i already configure it like this现在在服务器端我已经像这样配置它

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(Ordered.LOWEST_PRECEDENCE)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomAuthenticationProvider customAuthenticationProvider;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    public SecurityConfig() {
        super();
        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.cors().configurationSource(corsConfigurationSource()).and().csrf().disable()
            .exceptionHandling().and().authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
            .antMatchers(HttpMethod.GET, "/api/v1/cache/**").permitAll()
            .antMatchers("/api/v1/**").authenticated().and().authorizeRequests()
            .and().httpBasic();
    }

    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(Arrays.asList("Access-Control-Allow-Headers", 
        "Access-Control-Allow-Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", 
        "Origin", "Cache-Control", "Content-Type", "Authorization", "Ack", "ack", "ackwhatever", "goddamnack"));
        configuration.setAllowedMethods(Arrays.asList("DELETE", "GET", "POST", "PATCH", "PUT"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Override
    public void configure(final WebSecurity web) throws Exception {
        web.ignoring().antMatchers(HttpMethod.OPTIONS).antMatchers("/api/v1/login/*");
    }

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customAuthenticationProvider);
    }

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

even in the spring filter i put the header allowance即使在 spring 过滤器中,我也放了 header 余量

public class HttpRequestAuditFilter implements Filter {

    private static final Logger LOG = LoggerFactory.getLogger("access");
    private static final int MAX_PAYLOAD_LENGTH = 10000;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        if ((request instanceof HttpServletRequest)
            && !(request instanceof ContentCachingRequestWrapper)) {
            request = new ContentCachingRequestWrapper((HttpServletRequest) request);
        }

        HttpServletResponse responseQ = (HttpServletResponse) response;
        HttpServletRequest requestQ = (HttpServletRequest) request;

        try {
            responseQ.setHeader("Access-Control-Allow-Origin", "*");
            responseQ.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            responseQ.setHeader("Access-Control-Max-Age", "3600");
            responseQ.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, content-type, ack, Ack");
            responseQ.setHeader("Access-Control-Expose-Headers", "x-requested-with, authorization, content-type, ack, Ack");

            if ("OPTIONS".equalsIgnoreCase(requestQ.getMethod())) {
                responseQ.setStatus(HttpServletResponse.SC_OK);
            } else {
                chain.doFilter(requestQ, responseQ);
            }

        } finally {
            if (requestQ instanceof HttpServletRequest) {
                performRequestAudit((HttpServletRequest) requestQ);
            }
        }
    }

    public void performRequestAudit(HttpServletRequest httpRequest) {
        ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(httpRequest, ContentCachingRequestWrapper.class);

        String payload = "";
        if (wrapper != null) {
            byte[] requestBuffer = wrapper.getContentAsByteArray();
            if (requestBuffer.length > 0) {
                int length = Math.min(requestBuffer.length, MAX_PAYLOAD_LENGTH);
                try {
                    payload = new String(requestBuffer,
                        0, length, wrapper.getCharacterEncoding());
                } catch (UnsupportedEncodingException unex) {
                    payload = "[Unsupported-Encoding]";
                }
            }
        }
        LOG.trace("{}|{}", payload, wrapper.getHeaderNames());
    }

}

When i try with curl i got the response even in the mobile app its work perfectly, only with browser that got error (the browser itself already --disable-web-security).当我尝试使用 curl 时,即使在移动应用程序中我也得到了响应,它工作得很好,只有浏览器出现错误(浏览器本身已经 --disable-web-security)。

Any help and explanation will be apreciated.任何帮助和解释将不胜感激。

Instead of providing the cors configuration class manually, let it be a bean and let spring take it up automatically, also remove the lowest order so that your configuration does not get overridden.与其手动提供 cors 配置 class ,不如让它成为一个 bean 并让 spring 自动占用它,同时删除最低顺序,以免您的配置被覆盖。 Also remove the spring filter that you created to manually add the headers in the response as when configured correctly spring security will automatically add those headers in response.还要删除您创建的 spring 过滤器以手动在响应中添加标头,因为正确配置时 spring 安全将自动添加这些标头作为响应。 @EnableGlobalMethodSecurity can be used along with any @Configuration annotated classes but try like: @EnableGlobalMethodSecurity可以与任何@Configuration注释类一起使用,但尝试如下:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomAuthenticationProvider customAuthenticationProvider;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    public SecurityConfig() {
        super();
        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
            .exceptionHandling().and().authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
            .antMatchers(HttpMethod.GET, "/api/v1/cache/**").permitAll()
            .antMatchers("/api/v1/**").authenticated().and().authorizeRequests()
            .and().httpBasic();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(Arrays.asList("Access-Control-Allow-Headers", 
        "Access-Control-Allow-Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", 
        "Origin", "Cache-Control", "Content-Type", "Authorization", "Ack", "ack", "ackwhatever", "goddamnack"));
        configuration.setAllowedMethods(Arrays.asList("DELETE", "GET", "POST", "PATCH", "PUT"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Override
    public void configure(final WebSecurity web) throws Exception {
        web.ignoring().antMatchers(HttpMethod.OPTIONS).antMatchers("/api/v1/login/*");
    }

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customAuthenticationProvider);
    }

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

If this doesn't work separate out the method level security configurations to another configuration class and keep the web security as a separate connfiguration.如果这不起作用,请将方法级别的安全配置分离到另一个配置 class 并将 web 安全作为单独的配置。

暂无
暂无

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

相关问题 预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段 - Request header field is not allowed by Access-Control-Allow-Headers in preflight response 预检响应中的 Access-Control-Allow-Headers 不允许请求 header 字段 x-xsrf-token - Request header field x-xsrf-token is not allowed by Access-Control-Allow-Headers in preflight response 在飞行前响应中,Access-Control-Allow-Headers不允许在Request标头字段中使用cors enable Access-Control-Allow-Origin - cors enable in Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response Angular Spring Boot:重定向错误:在飞行前响应中Access-Control-Allow-Headers不允许请求标头字段Content-Type - Angular Spring Boot: Redirection error: Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response CORS 策略:无法解析预检响应中的 Access-Control-Allow-Headers 响应头字段 - CORS policy: Cannot parse Access-Control-Allow-Headers response header field in preflight response 对预检请求的响应未通过访问控制检查:不存在“Access-Control-Allow-Origin”标头。 服务器错误 - Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present . Server error 对预检请求的响应未通过访问控制检查:不存在“Access-Control-Allow-Origin”标头 - Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present 如何从其他来源访问网址? 即使存在Access-Control-Allow- *标头,预检请求也将返回401 - How to access url from another origin? Preflight request returns 401 even if Access-Control-Allow-* headers is present CORS:对预检请求的响应未通过访问控制检查:预检请求不允许重定向 - CORS : Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request 如何处理“对预检请求的响应未通过没有访问控制允许来源 header 存在于请求的资源上”来自 angular - How to handle “Response to preflight request doesn't pass No Access-control-Allow-Origin header is present on requested resource ” from angular in BE
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM