同源限制及解决方案

一.什么是同源?

1.知识背景

使用Ajax技术,向服务器端发送请求,是同一个网站的客户端向同一个网站的服务器端发送请求。
但是在实际的工作当中,我们通常会遇到这样的场景:需要获取的数据,在其他的服务器中。这时,就需要这个服务器端提供的请求地址,获取我们想要的数据。
这时,就存在一个问题。Ajax技术只能向自己的服务器发送请求。如果想向其他的服务器端发送Ajax请求,这是不被允许的。原因是浏览器有同源政策的限制。浏览器不允许Ajax向除了自己以外的其他服务器发送请求。这是浏览器给予Ajax技术的限制。

2.同源的定义

多个请求或者页面是否来自同一个服务器端。如果相同,就是说他们是同源的。
关于同源的一些具体规定:
如果两个页面拥有相同的协议,域名和端口,那么这两个页面就属于同一个源,任何一项不符合就是不同源。

示例结果原因
http://company.com/dir2/other.html同源只有路径不同
http://company.com/dir/inner/another.html同源只有路径不同
https://company.com/secure.html失败协议不同
http://company.com:81/dir/etc.html失败端口不同 ( http:// 默认端口是80)
http://new.company.com/dir/other.html失败主机不同

3.同源政策的目的

同源政策是为了保证用户信息的安全,防止恶意的网站窃取数据。

非同源而限制的三种行为:

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

最初的同源政策是:A网站在浏览器设置的Cookie,B网站不能访问。
Cookie一般是保存登录状态的,如果用户没有退出,其他人获取Cookie,就可以直接登录。

随着互联网的发展,同源政策也越来越严格。在不同源的情况下,其中有一项规定就是无法向非同源地址发送Ajax请求。
如果请求,浏览器就会报错。

这其中有一些细节,就是请求实际上是能够发出去的,只是浏览器拒绝接收服务器返回的结果,所以最终的请求还是失败的。

二.如何解决向其他服务器发送请求

不同源的网站之间,是不允许发送Ajax请求的。
但是现实的开发中,我们又有这样的需求。
到底如何解决浏览器的同源限制呢?

实际上方法有很多种,
先来看第一种:使用JSONP解决同源问题。

1.使用JSONP解决同源问题

这种解决方案,已经不属于Ajax请求的范围了。但是它能够模拟出Ajax请求的效果。
JSONP解决方案,实际上就是绕过浏览器同源政策的限制,向非同源服务器端发送请求。JSONP是 JSON with padding的缩写,含义只有了解这种方案才能明白。
这种解决方案,需要前后端开发人员配合完成。

以下是JSONP解决的步骤:

(1).将不同源的服务器端请求地址,写在script标签的src属性中。

<script src="www.example.com"></scritp>

因为在浏览器端,并不是所有能够发送请求的途径,都受同源政策的影响。
script标签的src属性就拥有发送请求的能力,但是它就不受同源政策的影响。
也就是说,在script标签的src属性中,可以写非同源请求地址。
比如引入jQuery的时候

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>

JSONP这种解决方案,利用的就是script标签的这一特性。

注意:请求地址可以是任何形式的,不必是.js结尾。

但是有一个前提:请求地址不管什么样,它必须返回合法的JavaScript代码。因为script标签在加载完请求地址中的内容后,会把内容当做JavaScript代码来执行。

这是JSONP解决方案中的第一步:将非同源的请求地址,写在script标签的src属性中。因为script标签的src属性是不受同源政策影响的。

(2).服务器端响应数据写法

 var data = 'fn({name: "张三", age: "20"})';
 res.send(data);

服务器端响应数据必须是一个函数的调用,当浏览器通过script标签将响应内容加载完以后,会自动将响应内容当做JavaScript代码执行。

实际上响应加载完以后,会立即调用这个函数。真正要发送给客户端的数据需要作为函数调用的参数。

在服务器端,这个响应内容必须是个字符串。在字符串当中,包裹函数调用的代码。因为,如果不是字符串,只是个函数,它会在服务器端被执行。

返回函数调用的同时,还要把客户端真正需要的数据,写在函数调用实参的地方。因为函数在客户端执行的时候,客户端可以通过形参对应这个数据。也就是可以获取服务器端返回的数据了。

注意:函数在客户端被调用,在调用之前,客户端要先准备好函数的定义。这样函数才能被调用。

(3).在客户端准备好函数的定义

//在客户端全局作用域下定义函数 fn。
function fn (data) { console.log(data); }

当script标签加载完服务器端的响应以后,会直接调用这个准备好的函数。如果客户端没有定义这个函数,代码将会报错。

需要注意:

  • 函数必须定义在全局作用域下。
  • 函数定义的代码必须写在script标签的上面。

这样在执行函数调用的时候,才能找到这个函数定义。保证在函数调用的时候,能找到函数的定义部分。

服务器端在返回函数调用的时候,已经把真正的数据作为函数的实参了,所以在函数定义的时候,可以直接写一个形参和实参相互对应。

(4).处理服务器端返回的数据

函数被调用后,形参对应了实参。这时就可以在函数内部对数据进行具体的处理。
在 fn 函数内部对服务器端返回的数据进行处理。

function fn (data) { console.log(data); }

(5).代码示例

在一号服务器的HTML输入代码:

//将非同源地址写到script标签的src属性中
<script src="http://localhost:3001/test"></scritp>
//定义接收函数
<script>
	//定义形参data接收数据
	 function fn(data){
	 	console.log(data);
	 }
</scritp>
//将非同源地址写到script标签的src属性中
<script src="http://localhost:3001/test"></scritp>

在二号服务器输入代码:

//获取请求,调用客户端定义好的函数。
const app = express();
app.get('/test', (req,res)=>{
	//调用客户端定义的函数,传输实参
	const result = 'fn({name:"张三"})';
	res.send(result);
})

利用script标签可以发送非同源请求的特性,在服务器端返回函数调用的代码,当客户端加载完成这个响应之后,会被客户端当做JavaScript代码来执行。
此时客户端要提前准备好函数定义,等待接收服务器返回的数据。

这时再理解 JSONP:JSON with padding。
将JSON数据作为填充内容,在服务器端将JSON数据作为函数的参数,将JSON数据填充到函数当中。这也是JSONP方案的核心。

2.后端解决,接口配置

3.配置nginx解决

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值