Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 545|回复: 0

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

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-6-21 22:06:21 | 显示全部楼层 |阅读模式

    一、什么是站点跨域

    了解跨域之前, 先了解下什么同源策略?
    百度百科:
    同源策略(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文件),将这个文件下载下来,那么浏览器会执行这个文件,而这个文件就包含别的站点的访问数据.具体实现方法如下:

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-25 10:26 , Processed in 0.072387 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表