跨域配置
在 web 应用程序中,当发起一个跨域请求,
A.example.com 发送请求
POST 请求会发送一个预检请求(OPTIONS),GET 不会
首先是请求。预检请求是 OPTIONS 包含三个预检请求标头的某种组合的请求: Access-Control-Request-Method 、 Access-Control-Request-Headers 和 Origin 。
如控制台提示如下内容:
Access to XMLHttpRequest at 'http://B.example.com' from origin 'http://A.example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
POST http://B.example.com/XXX net::ERR_FAILED
可以在 http://B.example.com 请求拦截器判断,如过是预检请求,就返回 200 状态码
# python flask
@app.before_request
def before_rest_request():
if request.method == 'OPTIONS':
response = make_response('ok')
response.status_code = 200
return response
else:
# 放行
return None
B.example.com 响应配置响应标头
可在请求拦截器响应处添加标头、或者在负载均衡器响应添加标头
Access-Control-Allow-Headers
Access-Control-Allow-Credentials
Access-Control-Allow-Methods
Access-Control-Allow-Origin
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Methods: POST, GET,PUT,OPTIONS,DELETE
Access-Control-Allow-Origin: $http_Origin
CORS 访问不通过,chrome 控制台的一些提示
- 缺失 Access-Control-Allow-Credentials
Access to XMLHttpRequest at 'http://B.example.com' from origin 'http://A.example.com' has been blocked by CORS policy:
The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.
The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
解决办法:配置B.example.com的响应头
Access-Control-Allow-Credentials: true
当请求的凭据模式包括 ( Request.credentials )时,浏览器只会在 Access-Control-Allow-Credentials 值为 true 时,将响应暴露给前端 JavaScript 代码。
fetch(url, {
credentials: "include",
});
import axios from 'axios'
import store from '@/store';
// create an axios instance
const service = axios.create({
// baseURL: "custom base url", // url = base url + request url
withCredentials: true, // send cookies when cross-domain requests
timeout: 300000, // request timeout
headers: {
'Content-Type': 'application/json;charset=UTF-8'
}
})
注意: Access-Control-Allow-Credentials 设置为 true,Access-Control-Allow-Origin不能设置为星号(*),而应该指定具体的域名或IP地址($http_Origin)。
结果
B.example.com 配置好OPTIONS和响应标头之后,A.example.com 就能正常访问B.example.com的资源