在与不同域通信时使用 POST 获取 400 错误请求错误

Posted

技术标签:

【中文标题】在与不同域通信时使用 POST 获取 400 错误请求错误【英文标题】:Getting 400 bad request error using POST while communicating to different domain 【发布时间】:2015-12-25 12:32:40 【问题描述】:

我们有两个用于 UI 和服务器的项目,它们都在不同的域上运行。对于 UI,我们使用 Angular JS,对于服务器端,我们使用 Spring 并向客户端提供 JSON 响应。由于 CORS 问题,我们无法与服务器通信。我们用谷歌搜索并尝试了不同的解决方案。我们找到了以下链接。

https://htet101.wordpress.com/2014/01/22/cors-with-angularjs-and-spring-rest/

我们做了链接中提到的任何事情。它适用于 GET 请求,但不适用于 POST 请求。当我们执行 POST 请求时,我们会收到 400 Bad Request。请查看以下详细信息以获取更多信息。

    远程地址: IP:8080 请求网址: http://IP:8080/controller/addLogin 请求方法: 发布 状态码: 400 错误请求

响应标头:HTTP/1.1 400 错误请求服务器:Apache-Coyote/1.1 访问控制允许来源:* 访问控制允许方法:POST, 获取,选项,删除访问控制最大年龄:3600 Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, 接受 Content-Type: text/html;charset=utf-8 Content-Language: en 内容长度:1113 日期:2015 年 9 月 28 日星期一 09:33:21 GMT 连接: 关闭

请求标头:POST /controller/addLogin HTTP/1.1 主机: 192.168.5.131:8080 连接:keep-alive 内容长度:41 编译指示:无缓存缓存控制:无缓存接受:应用程序/json,文本/纯文本, / 来源: localhost:1337 用户代理: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36 Content-Type: 应用程序/json;charset=UTF-8 引用: localhost:1337/login.html 接受编码:gzip,放气 接受语言:en-US,en;q=0.8

得到这个之后,我们在客户端添加了以下行,正如我们在 stacloverflow 中的一些解决方案中看到的那样。但错误仍然相同。

  $httpProvider.defaults.useXDomain = true;
  $httpProvider.defaults.withCredentials = true;
  $httpProvider.defaults.headers.common['Access-Control-Allow-Credentials'] = true;
  delete $httpProvider.defaults.headers.common["X-Requested-With"];
  $httpProvider.defaults.headers.post['Content-type'] = "application/json";

请帮助我们解决这个问题。

更新问题:

我们做了下面答案中提到的确切更改。然后我们得到了像

这样的异常
 org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'corsFilter' is defined for enabling cors.

为了解决这个问题,我们创建了 bean

<bean id="corsFilter" class="com.prototype.helper.SimpleCORSFilter" /> 

在 root-context.xml 文件中。但是我们仍然没有运气,我们仍然收到 400 个错误请求,例如

POST http://IP 地址:8080/controller/addLogin 400(错误请求)。

下面是我们所做的过滤器类和 web.xml 配置:

public class SimpleCORSFilter extends OncePerRequestFilter 

 // private Set<String> whitelist = Sets.newHashSet("[AllowedOrigin1]", "[AllowedOrigin2]");

     @Override
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                     FilterChain filterChain) throws ServletException, IOException 

          String originHeaderFromClient = request.getHeader("Origin");
          response.setHeader("Access-Control-Allow-Origin", originHeaderFromClient);
          response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
          response.setHeader("Access-Control-Max-Age", "3600");
          response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization,Content-Type");
          filterChain.doFilter(request, response);
     


web.xml:

    <filter>
        <filter-name>corsFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>corsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

【问题讨论】:

【参考方案1】:

如果您在浏览器的开发人员选项中检查网络选项卡,您可能会看到浏览器在发出 POST 调用之前正在对服务器进行 OPTIONS 调用。

默认情况下,Spring 的 DispatcherServlet 会阻止 OPTIONS 调用进入您的应用程序。意思是,OPTIONS 调用不会通过。您的浏览器认为您尝试访问的服务器不支持 CORS,因此阻止调用通过。

我们实现了一个过滤器,并在 web.xml 中使用DelegatingFilterProxy 连接它,如下所示:

<filter>
        <filter-name>corsFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>corsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

在过滤器的doFilter 方法中,做了以下操作:

 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException 
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String originHeaderFromClient = request.getHeader("Origin");
        response.setHeader("Access-Control-Allow-Origin", <<acceptedOrigins>>;
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization,Content-Type");
        chain.doFilter(request, response);

这样,所有调用都将获得Access-Control-Allow-Origin 标头,而与GET/POST 无关。而且它还可以让控制器保持 CORS 标头特定设置的清洁(如果您有多个控制器,这会很痛苦)。

【讨论】:

感谢您的回答。我们按照您的建议进行了更改,但仍然无法正常工作。我们通过代码更改更新了问题。 你确定过滤器被调用了吗?您的根上下文是如何加载的?您是否从客户端获取原始标头?理想情况下,您不应该在您的来源中设置客户端的 IP。您应该定义您接受来自哪些来源的请求。 是的过滤器正在被调用。因为当我们在调试模式下运行应用程序时,它会首先进入过滤器。正在使用 web.xml 文件中的 context-param 加载根上下文。从客户端获取原始标头为IPAddress:1337 并在服务器端设置相同,如下所示 String originHeaderFromClient = request.getHeader("Origin"); response.setHeader("Access-Control-Allow-Origin", originHeaderFromClient);我们在客户端使用的代码与下面的链接相同。metabroadcast.com/blog/…

以上是关于在与不同域通信时使用 POST 获取 400 错误请求错误的主要内容,如果未能解决你的问题,请参考以下文章

spring跨域 post 400 错误的请求怎么解决

在 Jquery Ajax POST 中获取 400 错误请求错误

使用 axios 获取 400 错误错误请求

get请求400错误,post请求405错误

apache - 域 Debian 8 中的错误 400

CORS 错误仅与 400 错误请求反应获取请求