angularjs post 跨域 Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

现象:

1. angular http 不配置data(请求参数)时不报错

2. 加上请求参数后,报错

3. 服务端response.headers().set(HttpHeaders.Names.ACCESS_CONTROL_ALLOW_HEADERS, HttpHeaders.Names.CONTENT_TYPE);后ok

 

经查

1. angularjs默认 application/json

2. 浏览器将跨域请求分为简单请求和复杂请求,显然angular默认是复杂请求

3. 在正式跨域的请求前,浏览器会根据需要,发起一个“PreFlight”(也就是Option请求),用来让服务端返回允许的方法(如get、post),被跨域访问的Origin(来源,或者域),还有是否需要Credentials(认证信息)

如果跨域的请求是Simple Request(简单请求 ),则不会触发“PreFlight”。

4. 具体规则取决于浏览器实例 

5. 对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段(详见下文),就知道出错了,从而抛出一个错误,被XMLHttpRequestonerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。

6. 非简单请求,浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。服务器收到"预检"请求以后,检查了OriginAccess-Control-Request-MethodAccess-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。如果浏览器否定了"预检"请求,会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段。这时,浏览器就会认定,服务器不同意预检请求,因此触发一个错误,被XMLHttpRequest对象的onerror回调函数捕获。控制台会打印出如下的报错信息。

在本例中,如果浏览器请求(首次Pre请求)包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。

 

 

附录:

https://blog.csdn.net/wangjun5159/article/details/49096445

https://blog.csdn.net/yangyiboshigou/article/details/78738228

https://blog.csdn.net/java_green_hand0909/article/details/78740765  前后两端把跨域说的很清楚,cookie等

https://blog.csdn.net/badboyer/article/details/51261083 chrome不行,火狐可以,对比了Pre Req的Request Header,另外有张图不错

 

PreFlight:

 

posted on 2018-08-31 15:03  silyvin  阅读(557)  评论(0编辑  收藏  举报