sosfiw
sosfiw
发布于 1个月前

解决异步跨域请求CORS(跨域资源共享)报错 No 'Access-Control-Allow-Origin' header is present on the requested resource

Access-Control-Allow-Origin

错误

Failed to load http://localhost:8081/request: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access.

原因

No 'Access-Control-Allow-Origin' header这基本是跨域请求遇到的第一个错误。浏览器基于同源政策,它会禁止AJAX发起非同源请求,其中同源包括三同:协议相同(如http),域名相同以及端口相同。

CORS则是允许浏览器向跨源服务器发起请求。这需要服务器端支持。

解决

解决跨域请求的第一个问题就是在响应的头信息加上Access-Control-Allow-Origin。

指定域名

Access-Control-Allow-Origin: http://www.example.com

允许所有域名访问

Access-Control-Allow-Origin: *

Access-Control-Allow-Credentials

错误场景
考虑下一个登陆功能,进入登录页面,我们向服务器请求验证码,验证码存放在session里。用户输入登录信息以及验证码发起异步跨域请求登录,你会发现,每次验证都是验证码不正确。

原因

查看下验证码的http和验证登陆的http请求的响应头信息Set-Cookie,你会发现两次请求的SessionId是不相同的。

CORS请求默认不发送Cookie和HTTP认证信息,如果我们想让CORS保持会话,我们需要服务器和浏览器端支持。

服务器端需要添加Access-Control-Allow-Credentials响应头信息:

Access-Control-Allow-Credentials: true

浏览器端需要在AJAX请求添加withCredentials属性:

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

预检请求(preflight)

错误

Failed to load http://localhost:8081/auth.json: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.

原因

非简单请求的CORS请求(包括PUT,DELETE或Content-Type类型是application/json),浏览器会在正式请求前,增加一次HTTP的OPTIONS查询请求,称为预检请求。预检请求目的是为了检查正式请求的域名,头信息以及HTTP 请求方法是否符合要求。预检请求失败则不会发起正式请求。

如上面的错误提示,content-type没有在被允许的头信息里。

解决

使用Access-Control-Allow-Headers添加允许的头信息,如content-type

Access-Control-Allow-Headers:content-type

对于多个需要被允许的头部,使用逗号隔开,如:

Access-Control-Allow-Headers:x-requested-with,content-type