同源策略与跨域请求
一、同源策略
- 所谓同源是指,域名,协议,端口的相同,同源策略(Same origin policy)则是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
- 同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。浏览器的同源策略,出于防范跨站脚本的攻击,禁止客户端脚本(如 JavaScript)对不同域的服务进行跨站调用(通常指使用XMLHttpRequest请求)。
二、跨域请求
- 有时候我们需要访问非同源网站的资源,这时候就需要做跨域请求了,JSONP和CORS是完成跨域请求的两种方式
1、JSONP实现跨域请求:
JSONP(JSON with Padding)是数据格式JSON的一种“使用模式”,可以让网页从别的网域要数据。根据 XmlHttpRequest 对象受到同源策略的影响,而利用 script元素的这个开放策略,网页可以得到从其他来源动态产生的JSON数据,这种使用模式就是JSONP。用JSONP抓到的数据并不是JSON,而是任意的JavaScript,用 JavaScript解释器运行而不是用JSON解析器解析。所以,通过Chrome查看所有JSONP发送的Get请求都是js类型,而非XHR。 实现示例如下:
首先创建两个项目,一个端口为8000,一个为8008
1)基于JS实现:
在端口为8000的项目中建立一个模板,在body里写:
<button onclick="f()">sendAjax</button> <script> function addScriptTag(src){ var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); document.body.removeChild(script); } function func(name){ alert("hello"+name) } function f(){ addScriptTag("http://127.0.0.1:8008/SendAjax/?callbacks=func") //func为上面定义的函数,服务端会返回以你定义的函数名的方法,将获取的json数据传入这个方法完成回调 } </script>
在端口为8008的项目中的view.py里建立一个视图函数:
def SendAjax(request): import json dic={"k1":"v1"} callbacks=request.GET.get("callbacks") return HttpResponse("%s('%s')"%(callbacks,json.dumps(dic)))
2)基于jQuery实现:
jQuery也支持JSONP,可以使用$.getJSON(url,[data],[callback])方法:
8000的html改为:
<button onclick="f()">sendAjax</button> <script> function f(){ $.getJSON("http://127.0.0.1:8008/SendAjax/?callbacks=?",function(arg){ alert("hello"+arg) }); } </script>
8008的views不改动。
结果是一样的,要注意的是在url的后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callback后面的那个问号是内部自动生成的一个回调函数名。
3)用ajax实现:
8008的views不动,8000的html改为:
<script> function f(){ $.ajax({ url:"http://127.0.0.1:8008/SendAjax/", dataType:"jsonp", //必须有,告诉server,这次访问要的是一个jsonp的结果。 jsonp: 'callbacks', //jQuery帮助随机生成字符串 success:function(data){ alert("hi "+data) } }); } </script>
2、CORS实现跨域请求
- Cross-Origin Resource Sharing(CORS)跨域资源共享是一份浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,确保安全的跨域数据传输。现代浏览器使用CORS在API容器如XMLHttpRequest来减少HTTP请求的风险来源。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。服务器一般需要增加如下响应头的一种或几种:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
- 跨域请求默认不会携带Cookie信息,如果需要携带,请配置下述参数:
"Access-Control-Allow-Credentials": true
// Ajax设置
"withCredentials": true