手机版

使用jsonp和代理服务器解决跨域问题

时间:2021-09-03 来源:互联网 编辑:宝哥软件园 浏览:

本文将从实用的角度介绍如何使用jsonp和代理服务器解决方案来解决跨域问题,并分享给大家参考和学习。下面就不多说了。我们来看看详细的介绍。

为了保护用户的安全,浏览器引入了同源策略,即一个服务器页面不能访问另一个不同协议、域名和端口的服务器的数据。当页面需要跨服务器从另一个服务器访问数据时,就会发生跨域行为。以豆瓣的公共API(https://api.douban.com/v2/book/1220562)为例。目前我的服务器在http://127.0.0.133605000以下。豆瓣的服务器和我的服务器明显不一样。当服务器中的一个页面通过AJAX请求这个接口时,浏览器会发出如下警告,页面将无法获取数据:

在实际开发中,如果遇到这样的跨域问题,可以通过以下方法获取跨域数据:

在异构服务器的响应头中设置访问控制允许源允许跨域行为JSONP设置自己的代理服务器转发异构数据。对于设置访问控制允许源的第一种方法,可以在Python Flask构建的服务器下设置一个简单的装饰器:

from func tools import wrap sfr from flask import make _ responsedf Allow _ cross _ domain(fun): @ wrap(fun)def wrap _ fun(* args,* * kwargs): rst=make _ response(fun(* args,* * kwargs))rst . heads[' Access-Control-Allow-Origin ']=' * ' rst . heads[' Access-Control-Allow-Methods ']=' PUT,GET,POST,DELETE ' allow _ headers=' Referer,Accept,Origin,User-Agent '

//允许自定义头和corspp . all(' * ',函数(req,res,next){ RES . header(' Access-Control-Allow-Origin ',' * ');res.header('访问控制-允许-header ','内容类型,内容长度,授权,接受,X-Requested-With,your header field ');res.header('访问控制-允许-方法',' PUT,POST,GET,DELETE,OPTIONS ');if(req . method==' OPTIONS '){ RES . send(200);/使选项请求快速返回/} else { next();}});但是设置访问控制允许起源的方法有一个致命的缺陷,就是只能在提供接口的服务器上添加。如果服务器不是自己开发的(比如上面提到的豆瓣开放API),这种方法基本可以忽略,所以只剩下JSONP和代理服务器供我们自由发挥。关于JSONP和代理服务器解决跨域的介绍很多,但是没有具体的实际案例。本文将通过具体的实际案例来了解这两种跨域方式的具体实现。

写这篇文章的时候,我手边可以直接使用的后端解决方案是Flash搭建的RESTful服务器,前端解决方案是针对Ajax的Vue 1.0 vue-resource,所以下面介绍的具体实际操作都是在这两个环境下进行的。如果你的开发环境和这个不一样,没关系,本文会用最少的逻辑代码来展示跨域实现原理,其他的解决方案可以类比使用。

JSONP

浏览器的同源策略限制跨域Ajax对资源的请求,但是脚本标签中的资源可以跨域获取。我们经常通过脚本标签来引用其他服务器的js:

script src=' script jsonp的http:https://code.jquery.com/jquery-2.2.4.min.js'/the原理是利用浏览器动态创建脚本标签,将需要请求的API放在脚本标签的src中获取数据,不受同源策略的限制。

JSONP由回调函数和返回数据组成。当脚本创建src并引入资源时,调用回调函数。返回的数据(响应)作为回调函数的第一个参数传入,获得的不同源数据可以保存在回调函数中。具体来说,例如,当页面被加载时,我们获取数据并请求https://api.douban.com/v2/book/1220562:

//在vue中,回调函数需要被视为全局函数,否则在vue的生命周期中不会得到这个回调函数var d=null函数handleResponse(响应){ console.log(响应);d=响应;} compiled : function(){ var self=this;//jsonp var script=document . create element(' script ');//动态创建标签script . src=' https://API . douban.com/v2/book/1220562?回调=handleResponse ';//创建的src是请求的API。同时,您需要向这个src添加一个回调查询参数。参数名是您的回调函数名document . body . appendchild(script,document . body . first child);//插入新创建的脚本标签,类似于Ajax发起请求。//轮询资源获取是否完成。var timer=set interval(function(){ if(d){ console . log(' pending ')clear interval(timer);self . data=d;//将获取的数据分配给数据模型} },500);}此时页面刷新,浏览器不再发出访问-控制-允许-起源的跨域错误,输出脚本获取的数据:

JSONP的缺点

JSONP的缺点主要来自他的脚本引用资源的方式。JSONP的缺点如下:

JSONP通过脚本标签获取资源,意味着JSONP注定只能通过GET访问资源,GET以外的请求无法完成;JSONP通过src引用不同来源的代码。如果其他域中存在恶意代码,将会造成严重的网络安全问题。如果需要跨域的服务器不够可信,就必须放弃JSONP。为了确定JSONP请求是否成功,需要启动一个计时器来监控数据变化。针对JSONP的上述缺点,如果需要改进,需要使用代理服务器。

代理服务系统

代理服务器解决跨域问题的思路是使用代理服务器转发浏览器页面请求,因为同源策略的限制只存在于浏览器中,而在服务器端没有这种限制。常见的代理服务器方案包括反向代理服务器和服务器内转发。使用反向代理服务器的一个例子是Nginx的反向代理。通过修改Nginx的配置文件,可以将指定的不同源域名代理到当前服务器,浏览器正常情况下可以访问不同来源的资源。另一种方案是在服务器端转发来自不同来源的API,而不依赖反向代理服务器。本文主要介绍这种方法。

首先,代理服务器需要知道浏览器页面需要请求的api。所以页面需要把api作为参数传递给代理服务器,比如:/proxy/:api,API参数是完整的API链接,比如前面提到的豆瓣公共API:https://api.douban.com/v2/book/1220562.服务器转发API,Python中可以用请求发起HTTP请求,nodejs可以用request。服务器收到响应后,将响应结果返回给浏览器。具体实现也很简单。以Flask为例:

@ app . route('/proxy/path : URL ',Methods=[' get '])def get tasks(URL): r=requests。get (URL) # #请求转发conver _ r=eval(字节。decode (r. content)) # #做一些类型转换返回json.dumps(conver_r),200在浏览器端启动

自我。$ http . get('/proxy/https://API . douban.com/v2/book/1220562 ')。然后(函数(RES){ self . data=JSON . parse(RES . data)});此时打开浏览器控制台,可以看到服务器转发的请求结果,跨域成功。

代理服务器与JSONP相比的优势

与JSONP相比,使用代理服务器转发不同的源API的优势如下:

资源获取通过服务器端进行,资源请求可以根据需要转发的API选择GET以外的HTTP方式;请求的资源需要通过服务器转发给浏览器,服务器可以对资源进行处理,这样可以避免一些直接的恶意代码,比JSONP更安全;浏览器页面通常使用Ajax请求数据,并回调以知道请求是否完成,因此不需要使用计时器进行监控。代理服务器的缺点

使用代理服务器的缺点是将请求转发到不同的源资源。如果多个用户同时进行跨域请求,由于服务器需要进行额外的HTTP请求,服务器端的处理压降会变大,从而导致阻塞等一系列性能问题。如果需要更好的解决方案,需要使用反向代理服务器,如Nginx进行端口代理处理。

摘要

本文从实用的角度介绍了JSONP和代理服务器的跨域方法,并比较了两种方案的优缺点。如果有一些安全性要求较低的场景,可以直接使用JSONP进行跨域请求。如果需要额外的HTTP请求并且安全要求很高,则应该从服务器端发起跨域请求。当然还有其他跨领域的方案,需要读者根据自己的能力和判断来放弃。

好了,这就是本文的全部内容。希望本文的内容对你的学习或工作有一定的参考价值。有问题可以留言交流。谢谢你的支持。

版权声明:使用jsonp和代理服务器解决跨域问题是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。