第72篇 跨域的简单介绍

1.跨域的相关概念

1.1 什么是跨域

同源策略是由 Netscape 提出的著名安全策略,是浏览器最核心、基本的安全功能,它限制了一个源(origin)中加载文本或者脚本与来自其他源(origin)中资源的交互方式,所谓的同源就是指协议、域名、端口相同。
当浏览器执行一个脚本时会检查是否同源,只有同源的脚本才会执行,如果不同源即为跨域。

域名组成:
image

1.2 为什么会出现跨域

浏览器的同源策略,出于防范跨站脚本的攻击,禁止客户端脚本(如 JavaScript)对不同域的服务进行跨站调用(通常指使用 XMLHttpRequest 请求)。

1.3 浏览器的同源策略:Same-Origin Policy

  • 没有同源策略的危害
    防止恶行请求
    案例讲解:
    假设有一个黑客叫做小黑,他从网上抓取了一堆美女图做了一个网站,每日访问量爆表。
    为了维护网站运行,小黑挂了一张收款码,觉得网站不错的可以适当资助一点,可是无奈伸手党太多,小黑的网站入不敷出。
    于是他非常生气的在网页中写了一段js代码,使用ajax向淘宝发起登陆请求,因为很多数人都访问过淘宝,所以电脑中存有淘宝的cookie,不需要输入账号密码直接就自动登录了,然后小黑在ajax回调函数中解析了淘宝返回的数据,得到了很多人的隐私信息,转手一卖,小黑的网站终于盈利了。
    如果跨域也可以发送AJAX请求的话,小黑就真的获取到了用户的隐私并成功获利了!!!

1.4 跨域有哪些限制

  • Cookie、LocalStorage 和 IndexDB 无法读取。
  • DOM 无法获得。:钓鱼网站
  • AJAX 请求不能发送。

1.5 Ajax请求步骤:

(1)创建XMLHttpRequest 对象。
(2)使用open方法设置请求的参数。open(method, url, 是否异步)。
(3)发送请求。
(4)注册事件。 注册onreadystatechange事件,状态改变时就会调用。
(5)获取返回的数据,更新UI。

2.JSONP(JSON with Padding)

2.1 概念

原理就是利用了 script 标签不受同源策略的限制,在页面中动态插入了 script,script 标签的 src 属性就是后端 api 接口的地址,并且以 get 的方式将前端回调处理函数名称告诉后端,后端在响应请求时会将回调返还,并且将数据以参数的形式传递回去。

2.2 核心代码

前端:

	var script = document.createElement('script');
	script.src = 'http://127.0.0.1:2333/jsonpHandler?callback=_callback';
	document.body.appendChild(script);   

	var _callback = function(obj) {
	   for(key in obj) {
		 console.log('key: ' + key +' value: ' + obj[key]);
		}
	}

后端:

[HttpGet]
		[Route("jsonpForVue")]
		public void GetjsonpForVue(string callback)
		{

			TokenModelJwt tokenModelJwt=new TokenModelJwt(){
				Role="admin",
				Uid=1,
				Work="dsdf"
			};
			//string call = "({" + response + "})";
			string response = string.Format("\"name\":\"{0}\"", "zhagnsan");
			var modlestr = JsonConvert.SerializeObject(tokenModelJwt);
			string call = callback + "(" + modlestr + ")";
			Response.WriteAsync(call);
		}

2.3 优劣

劣:

  • 这种方式只能发生get请求;
  • 确定jsonp的请求是否失败并不容易,大多数框架的实现都是结合超时时间来判定;
  • 不太安全,可能也会受到攻击;

优:

  • 很简单
  • 老式浏览器全部支持,服务器改造非常小

3 Proxy代理

3.1 概念

  • vue-cli的proxyTable用的是http-proxy-middleware中间件
  • create-react-app用的是webpack-dev-server内部也是用的http-proxy-middleware
  • http-proxy-middleware内部用的http-proxy

跨域是浏览器禁止的,服务端并不禁止跨域

image

所以浏览器可以发给自己的服务端然后,由自己的服务端再转发给要跨域的服务端,做一层代理。

3.2 核心代码

前端:

proxy: {
	  // 配置多个代理
	  "/api": {
		target: "http://localhost:5000",//这里改成你自己的后端api端口地址,记得每次修改,都需要重新build
		//target: "http://localhost:58427",
		//target: "http://api.douban.com",
		ws: true,
		changeOrigin: true,
		pathRewrite: {
		  // 路径重写,
		  "^/apb": "" // 替换target中的请求地址
		}
	  }

image

3.3 优劣

缺点:不能用在生产环境,只能在开发环境;
优点:dev环境配置很简单,支持多个域名;

4 CORS,全称:Cross-Origin Resource Sharing(跨域资源共享)

4.1 概念

CORS是一种允许当前域(origin)的资源被其他域(origin)的脚本请求访问的机制。

当使用 XMLHttpRequest 发送请求时,浏览器如果发现违反了同源策略就会自动加上一个请求头 origin,后端在接受到请求后确定响应后会在 Response Headers 中加入一个属性 Access-Control-Allow-Origin,值就是发起请求的源地址(http://127.0.0.1:8888),浏览器得到响应会进行判断 Access-Control-Allow-Origin 的值是否和当前的地址相同,只有匹配成功后才进行响应处理。

简单请求

  • GET
  • HEAD
  • POST
  • 条件 2:Content-Type 的值仅限于下列三者之一:
  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

复杂请求

4.2 核心代码

后端配置

4.3 优劣

缺点:

  • 部分老的浏览器不支持

优点:

  • 支持所有 Http 谓词请求
  • 不用注意接口规则
  • 可用在生产环境

5 Nginx

概念:nginx解决跨域 是利用其反向代理的能力

5.1 跨域原理

Brower =》 host =》 nginx =》 目标地址服务器数据 =》 nginx =》 Brower
也就是说,nginx并不是通过监听brower的请求。而是作为一个服务器,接收外部对本机的请求。所以是先通过host,让请求指向本机,才会经过nginx。才能进行转发。

  • 首先,直接在浏览器地址栏中,输入某接口地址。是不会产生跨域问题的。
  • 只有当在某域名的页面中,由该页面发起的接口请求。才可能会跨域。
  • nginx就类似于这个浏览器地址栏,它接收到外部对它的请求( 注意,nginx只会接收别人对它的请求,而不会拦截浏览器的请求 ),再类似浏览器地址栏一样去请求某个接口。最后将请求到的内容返回回去

5.2 核心代码

server {
		listen       1005;
		server_name  localhost;
		location / {
			root   nuxt\Blog.Admin\dist;
			index  index.html index.htm;
		}
		location /api {
			rewrite  ^.+apb/?(.*)$ /$1 break;
			   include  uwsgi_params;
			proxy_pass   http://localhost:1004; #// 这是 netcore 端口
		}
		error_page  404              /404.html;
		error_page   500 502 503 504  /50x.html;
		location = /50x.html {
			root   html;
		}
	}

5.3 优劣

缺点:

  • 移植灵活性 低、每套环境配置可能均不相同

优点:

  • 对独立性强的小项目,使用nginx则可以降低你的开发成本,快速发开快速上线

6 Socket

WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

核心代码:

var ws = new WebSocket('wss://echo.websocket.org'); //创建WebSocket的对象。参数可以是 ws 或 wss,后者表示加密。

	//把请求发出去
	ws.onopen = function (evt) {
		console.log('Connection open ...');
		ws.send('Hello WebSockets!');
	};


	//对方发消息过来时,我接收
	ws.onmessage = function (evt) {
		console.log('Received Message: ', evt.data);
		ws.close();
	};

	//关闭连接
	ws.onclose = function (evt) {
		console.log('Connection closed.');
	};

7 其他

image

posted @ 2024-12-07 17:31  似梦亦非梦  阅读(61)  评论(0编辑  收藏  举报