django之同源策略

什么是同源策略

同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。

简单来说,端口不同或者域名不同,就会有庭院策略问题

什么是JSONP

首先提一下JSON这个概念,JSON是一种轻量级的数据传输格式,被广泛应用于当前Web应用中。JSON格式数据的编码和解析基本在所有主流语言中都被实现,所以现在大部分前后端分离的架构都以JSON格式进行数据的传输。

那么JSONP是什么呢? 
首先抛出浏览器同源策略这个概念,为了保证用户访问的安全,现代浏览器使用了同源策略,即不允许访问非同源的页面,详细的概念大家可以自行百度。这里大家只要知道,在ajax中,不允许请求非同源的URL就可以了,比如www.a.com下的一个页面,其中的ajax请求是不允许访问www.b.com/c.php这样一个页面的。

JSONP就是用来解决跨域请求问题的,那么具体是怎么实现的呢?

JSONP原理

ajax请求受同源策略影响,不允许进行跨域请求,而script标签src属性中的链接却可以访问跨域的js脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域。

JSONP的具体实现

<!DOCTYPE html>
<html>
<head>
    <title>GoJSONP</title>
</head>
<body>
 $(".jsonp_test").click(function () {
    $.ajax({
        url:"http://127.0.0.1:8008/service/",
        type:"get",
        dataType:"jsonp",     // 伪造ajax  基于script
        jsonp: 'callbacks',    //相当于?callbacks=alex
        //jsonpCallback:"alex",
        success:function (data) {
            console.log(data)
        }
    })
})
<button class='jsop_test'>测试</button>
</body> </html>
127.0.0.1:8000中的index.html
import json
def jsonp_test(request):
    func=request.GET.get("callbacks") #获取请求的callbacks参数
    info={"name":"fuyong","age":18} #定义数据
    return HttpRespons
import json
def jsonp_test(request):
    func=request.GET.get("callbacks") #获取请求的callbacks参数
    info={"name":"fuyong","age":18} #定义数据
    return HttpResponse("%s ('%s')"%(func,json.dumps(info))) #传json对象
http://127.0.0.1:8008/service/的views

 JSONP总结

一句话就是利用script标签绕过同源策略,获得一个类似这样的数据。ajax里边的callbacks本质上是(伪装成script标签src属性发送请求的方式)发送一个回调方法,参数data就是想得到的json数据。

CORS实现跨域请求

CORS:Cross-Origin Resource Sharing(CORS)跨来源资源共享是一份浏览器技术的规范,提供了 Web 服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,是 JSONP 模式的现代版。与 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest,这种方式的错误处理比 JSONP 要来的好 。另一方面,JSONP 可以在不支持 CORS 的老旧浏览器上运作。现代的浏览器都支持 CORS。

CORS对比JSONP

都能解决 Ajax直接请求普通文件存在跨域无权限访问的问题

  1. JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求
  2. 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理
  3. JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS

 CORS的实现思路

CORS背后的基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定请求或响应成功与否。

例如 localhost:63343 通过Ajax请求http://192.168.10.61:8080服务器资源时就会出现异常,其实数据已经获取到了,但是由于同源策略的限制给禁止了,提示说header里没有Access-Control-Allow-Origin,那么,我们在发送响应的时候的只需要给header里加上这个参数就行了。

 CORS的实现

CORS有很多种实现方式,这里介绍一种最简单最直观的的方式,就是修改views.py中对应函数,给它的响应头部添加Access-Control-Allow-Origin餐具允许其他域通过Ajax请求数据,如下:

def cors_test(request):
    info={"name":"egon","age":34,"price":200} #数据
    response=HttpResponse(json.dumps(info)) #序列化数据
    #response["Access-Control-Allow-Origin"]="http://127.0.0.1:8006" #指定ip可访问
    #response["Access-Control-Allow-Origin"]="*"#所有ip均可访问
    return  response #返回数据
views.py

下面的代码实现了通过添加中间件的方式实现跨域请求

class MiddlewareMixin(object):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MiddlewareMixin, self).__init__()
 
    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            response = self.process_request(request)
        if not response:
            response = self.get_response(request)
        if hasattr(self, 'process_response'):
            response = self.process_response(request, response)
        return response
 
class CORSMiddleware(MiddlewareMixin):
 
    def process_response(self,request,response):
        # 添加响应头
 
        # 允许你的域名来获取我的数据
        response['Access-Control-Allow-Origin'] = "*"
 
        # 允许你携带Content-Type请求头
        response['Access-Control-Allow-Headers'] = "Content-Type"
 
        # 允许你发送DELETE,PUT
        response['Access-Control-Allow-Methods'] = "DELETE,PUT"
 
        return response
cors.py
MIDDLEWARE = [
   .....
 
    'xxx.cors.CORSMiddleware',  # xxx为cors.py所在包的目录
]
settings

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2019-02-14 18:44  离人怎挽_wdj  阅读(213)  评论(0编辑  收藏  举报