示例
在http:*java.s.com域名下异步请求以下连接,均属于跨域请求。
$.get("http://php.s.com/1.png");
$.get("http://php.s.com/2.css");
$.get("http://php.s.com/1.js");
$.get("http://php.s.com/2.html");
以上请求均会得到类似以下信息的错误警告:XMLHttpRequest cannot load http://php.s.com/1.png. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://java.s.com' is therefore not allowed access.
什么是同源请求
所谓同源指的是三个相同
- 协议相同
- 域名相同
- 端口相同
有一个不同就不是同源,这里的域名是指全域名,并不只是根域名。a.x.com和b.x.com就不是同源,就跨域了。
AJAX跨域请求流程
跨域请求都是出现在ajax异步请求中。 以$.get(http://php.s.com/1.png); 请求为例:
当浏览器发现是ajax跨域请求时,会自动在请求头信息中添加一项
Origin:当前域名 Origin: http://java.s.com
服务器并不理会请求头中的Origin参数,进行正常http响应。
客户端浏览器会读服务器取响应头信息,如果响应头中没有Access-Control-Allow-Origin信息或Access-Control-Allow-Origin许可的域名中没有当前域名,
浏览器就会抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。注意,就算抛出错误,但是服务器返回的HTTP回应的状态码有可能是200。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE11。
Access-Control-Allow-Origin
允许所有或允许一个
以php为例:
1 允许所有请求,当然这样不安全
header("Access-Control-Allow-Origin:*");
2 允许一个域名跨域请求
header("Access-Control-Allow-Origin: http://www.baidu.com");
上面的设置只允许来自http:*www.baidu.com的跨域请求。
下面写法都是错误的:
//必须要加http,没有http,那么来自http://b2b2c.stest.com的跨域请求不能成功
header("Access-Control-Allow-Origin:*.stest.com");
//这样设置的结果等于没有设置,相当于拒绝所有域名的跨域请求。
header("Access-Control-Allow-Origin:*b2b2c.stest.com,java.stest.com");
//这样设置的结果等于没有设置,相当于拒绝所有域名的跨域请求。
//Access-Control-Allow-Origin只能设置一个域名,或都设置成*,支持所有域名。
其它语言/工具实现跨域请求
html方式实现
<meta http-equiv="Access-Control-Allow-Origin" content="http://stest.com">
nginx
location ~* \.(eot|otf|ttf|woff|svg)$ {
add_header Access-Control-Allow-Origin *;
}
apache
<VirtualHost *:80>
<FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
Header set Access-Control-Allow-Origin "*"
</FilesMatch>
</VirtualHost>
//FilesMatch是后加的,没有测试
怎样允许多个域名同时跨域请求
php实现方式:
//取得头信息
$header = getallheaders();
//允许跨域的域名
$allowHeader = array("http://java.s.com", "http://b2b2c.s.com");
//如果请求头中的Origin参数 在被允许的域名范围之内,就返回请求过来的头,这样就可以跨域了。
if (in_array($header["Origin"], $allowHeader)) {
header("Access-Control-Allow-Origin:" . $header["Origin"]);
}