什么是跨域
简单的理解就是因为浏览器同源策略的限制,a.com域名下的js无法操作b.com或者c.a.com域名下的对象
(浏览器在请求不同域的资源时,无法成功)
http://mail.163.com/index.html http代表协议 还可以是ftp协议 file 协议telnet协议mailto协议 mail代表服务器是邮件服务器,www代表是web服务器 163.com是域名,.com是顶级域名,/是根目录
{前面的协议或域名有任何一个不同就是跨域} index.html 是根目录下的文件端口号不同都算做不同的域。端口号8080和端口号8081就是两个不同的域。
事实上HTTP和HTTPS两个协议的url看上去都可以省略端口号,但是他们访问的默认端口不同HTTP默认访问80端口,HTTPS默认访问443端口,所以http访问https肯定是跨域
总之,协议、域名、端口任一不同便是跨域。
非同源限制
【1】无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
【2】无法接触非同源网页的 DOM
【3】无法向非同源地址发送 AJAX 请求
有三个标签可以跨域调用: <img src=> <link href> <script src=>
服务器方面 两个方法:反向代理和CORS
1.处理跨域方法一 :反向代理
通过在同域名的web服务器端创建一个代理,客户端直接发送请求给代理服务器,然后代理服务器会根据客户端的请求,从真实的资源服务器中获取资源返回给客户端。所以反向代理就隐藏了真实的服务器。
利用这种特性,我们可以通过将其他域名的资源映射成自己的域名来规避开跨域问题。
node.js和express、nginx皆可实现。
原理就是在监听到客户端请求后,启动一个代理服务器,然后获取代理服务器返回的结果,直接返回给客户端。
(1).当用户发送localhost:80/时会被代理服务器转发到http://localhost:81服务;
(2).当界面请求接口数据时,就会被nginx转发到http://localhost:81服务器上;
2.处理跨域方法二 :CORS
"跨域资源共享"(Cross-origin resource sharing)是W3C出的一个标准。
CORS的核心思想是通过一系列新增的HTTP头信息来实现服务器和客户端之间的通信。
(1)、普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
(2)、带cookie跨域请求:前后端都需要进行设置
【前端设置】
根据xhr.withCredentials字段判断是否带有cookie
var xhr = new XMLHttpRequest(); xhr.withCredentials = true; // 前端设置是否带cookie
【服务端设置】
服务器端对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问
// 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/' response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); // 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示 response.setHeader("Access-Control-Allow-Credentials", "true"); // 提示OPTIONS预检时,后端需要设置的两个常用自定义头 response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");
// Node.js跨域后台设置 res.writeHead(200, { 'Access-Control-Allow-Credentials': 'true', // 后端允许发送Cookie 'Access-Control-Allow-Origin': 'http://www.domain1.com', // 允许访问的域(协议+域名+端口) /* * 此处设置的cookie还是domain2的而非domain1,因为后端也不能跨域写cookie(nginx反向代理可以实现), * 但只要domain2中写入一次cookie认证,后面的跨域接口都能从domain2中获取cookie,从而实现所有的接口都能跨域访问 */ 'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly' // HttpOnly的作用是让js无法读取cookie });
前端 :document.domain和JSONP
1. 设置document.domain解决无法读取非同源网页的 Cookie问题 (此方案仅限主域相同,子域不同的跨域应用场景。)
因为浏览器是通过document.domain属性来检查两个页面是否同源,因此只要通过设置相同的document.domain,两个页面就可以共享Cookie
// 两个页面都设置 document.domain = 'test.com';
2. JSONP(JSONP只支持GET方式不支持POST方式)
核心思想:网页通过添加一个<script>元素
,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
<script src="http://test.com/data.php?callback=dosomething"></script> // 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字 // 处理服务器返回回调函数的数据 <script type="text/javascript"> function dosomething(res){ // 处理获得的数据 console.log(res.data) }