一、什么是站点跨域
了解跨域之前, 先了解下什么同源策略? 百度百科: 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。 同源:同一个协议, 同一个主机, 同一个端口 即同一个站点, 比如说IIS服务器, 一个站点只能绑定一个端口
那为什么需要同源策略的支持呢? 因为假设你已经登陆一个站点, 服务器已经将一些敏感信息返回到了客户端, 如果此时你的站点代码中有一段访问其他站点的代码, 这段代码又是获取用户的铭感信息, 又比如说用户在访问银行网站,并且没有登出。然后他又去了任意的其他网站, 刚好这个网站有恶意的js代码,在后台请求银行网站的信息。因为用户目前仍然是银行站点的登陆状态,那么恶意代码就可以在银行站点做任意事情。例如,获取你的最近交易记录,创建一个新的交易等等。那是相当不安全的. 所以同源策略是相当重要的.即如果访问了一个站点, 那么用户在访问这个站点的所有内容必须是这个站点的内容, 不允许访问其他站点的内容.
二、"同源政策"限制的功能
随着互联网的发展,"同源政策"越来越严格。目前,如果非同源,共有三种行为受到限制。
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
虽然这些限制是必要的,但是有时很不方便,合理的用途也受到影响。
三、为什么要规避同源策略
1、Cookie问题
假设我们有一个站点,由于业务的扩展,一个站点无法承受这么大的业务量,常规的做法是将业务拆分,拆分成不同的站点.但是理论上拆分出来的站点还是归属于原来的站点,因为逻辑上这些站点属于一个应用程序,所以我们需要使用多级域名的技术,给主站点分配一个主域名,其他的站点分配该主域名的子域名,集体请参考IIS 站点部署多级域名.
但是由于"同源策略"的影响,其中的一个业务站点无法共享其它站点的Cookie,因为它们只是一级域名相同,二级域名并不相同,但是理论上它们时同一个应用程序,所以Cookie必须共享.
问题重现,在主站点的MVC控制器的Index方法写入一个Cookie信息,代码如下:
public ActionResult Index()
{
var cookie = new HttpCookie("userInfo", "xiaochao");
cookie.Expires = DateTime.Now.AddDays(1);//设置cookie一天后过期
Response.SetCookie(cookie);
return View();
}
在主站点的Index页面下读取cookie,代码如下:
<script>
$(function () {
//输出在主站点设置的cookie
$(function () {
//输出cookie
var username = document.cookie.split(";")[0].split("=")[1];
if (username) {
alert(username);
}
else {
alert("cookie没有写入");
}
});
});
注意在打开浏览器前,请先清空浏览器缓存,主站点浏览器输出:
ok,Cookie正常输出,接着打开业务站点1,js代码和上面的一样
ok,问题很明显,主站点并没有将cookie共享到业务站点,所以这个问题必须解决.
解决方案如下:
(1)、服务器端设置Cookie的Domain属性
通过主站点服务器端(不一定在主站点,也可以是业务站点,亲测有效,这里不做演示)设置Cookie的Domain属性为一级域名,这样所有的在一级域名下的二级域名站点都可以共享Cookie,代码如下:
public ActionResult Index()
{
var cookie = new HttpCookie("userInfo", "xiaochao");
cookie.Expires = DateTime.Now.AddDays(1);//设置cookie一天后过期
cookie.Domain = "a.com";//设置Domain属性,这样这个域名下的所有的子域名,所有站点都共享Cookie
Response.SetCookie(cookie);
return View();
}
主站点输出:
业务站点1输出:
ok,说明在Cookie设置生效了,所有的站点共享了Cookie.
3、.Net 站点下跨域问题的重现
现在有两个站点,一个MVC站点,一个WebApi站点
此时有个业务,MVC站点需要访问Api站点下面的一个Json方法,拿到对应的业务数据
Api站点的方法如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace SiteApi.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Title = "Home Page";
return View();
}
/// <summary>
/// 给MVC站点调用的方法
/// </summary>
/// <returns></returns>
[HttpPost]
public ActionResult GetData()
{
return Json("666");
}
}
}
MVC页面的调用代码如下:
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script>
$(function () {
$.post("http://localhost:50187/Home/GetData", function (data) {
alert(data);
});
});
</script>
运行站点效果如下:
数据没有出来,打开控制台发现了这个Error。百度提示,浏览器出现跨域行为,需要添加Asscss-COntrol-Allow-Origin头.
4、为什么要规避跨域 先说说为什么要规避跨域? 上面的例子可以说明,且假设有一个应用集群,我们建设了一个用户中心,该用户中心提供一些用户验证的功能,如登陆校验、权限等功能.那必须的,这个用户中心是以站点的形式存在,而应用集群中所有的应用必须能访问该用户中心站点,来校验用户的可用性, 但是用户中心站点对于应用集群中所有的应用来说都属于外部应用,所以违反了同源策略,但是这个功能必须要实现.所以这种情况下,必须采用技术手段来规避同源策略.
5、解决方案
(1)、跨域资源共享 CORS 技术
Ajax请求受限于同源策略,而这种技术能解决这种限制.但是需要服务器和浏览器的协作,IE浏览器不能低于IE10.
(1)、Jsonp技术
下面用Jsonp技术来解决这个问题.在了解这个技术之前,你需要知道虽然同源策略不允许跨域Ajax请求,代码支持跨域的文件访问,这些文件包括图片、Js文件等.这里我们就可以用特定的Ajax请求去访问一个Js文件(也可以是html文件),将这个文件下载下来,那么浏览器会执行这个文件,而这个文件就包含别的站点的访问数据.具体实现方法如下:
|