.Net 站点跨域问题及解决方法

一、什么是站点跨域

了解跨域之前, 先了解下什么同源策略?
百度百科:
同源策略(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.

 

(2)、客户端Js脚本设置

 

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文件),将这个文件下载下来,那么浏览器会执行这个文件,而这个文件就包含别的站点的访问数据.具体实现方法如下:

 

posted @ 2018-11-08 19:40  郑小超  阅读(2185)  评论(0编辑  收藏  举报