一, 引子
我现在开启了两个 django 项目, 分别叫 Demo1 和 Demo2,Demo1 中有一个路径'http://127.0.0.1:8000/index/', 对应的视图是 index 视图返回一个 index 页面, 页面中只有一个 button 按钮, 按钮绑定了一个单击事件, 点击之后会发送一个 Ajax 请求, 请求的路径为'http://127.0.0.1:8001/ajax/',Demo1 的 ip 和端口号是:'http://127.0.0.1:8000/',Demo2 的 ip 和端口号是:'http://127.0.0.1:8001/'. 前面一段描述就是在 Demo1 项目的一个页面向 Demo2 项目发送一个 Ajax 请求, 在 Demo2 有对应的路径和视图来处理请求, 并返回值. 我们运行一下. 报错如下:
这就是一个已拦截的跨域请求的错误, 错误内容是 CORS 头少 "Access-Control-Allow-Origin". 这就是我们用 Ajax 发送一个跨域请求出现的错误, 这就是今天我要处理的一个问题.
二, 同源策略
同源策略 (Same origin policy) 是一种约定, 它是浏览器最核心也最基本的安全功能, 如果缺少了同源策略, 则浏览器的正常功能就会受到影响, 可以说 web 是构建在同源策略基础之上的, 浏览器只是针对同源策略的一种实现.
同源策略, 它是由 Netscape 提出的一个著名的安全策略. 现在所有支持 JavaScript 的浏览器都会用这个策略. 所谓的同源, 即指: 域名, 端口, 协议同时相同. 比如说你用 Ajax 发请求时, 会检查你发送的请求是否发送路径是否 Ajax 所在的 JavaScript 属于同源, 即是两者的 ip, 端口, 协议相同. 如果不是同源, 浏览器就会报错, 提示拒绝访问.
想要实现用 Ajax 发送跨域请求有两种方式, 一是 JSONP, 而是 cors.
三, 基于 JSONP 的 Ajax 跨域请求
1, 版本 1
我们在用 script 引入 JS 代码, 有时用的是网上路径, 意思就是在我们的项目去请求其他项目的, 如:
这种情况下是可以请求成功的, 于是, 我们可以运用这一功能, 给 button 按钮绑定事件, 事件的功能是创建一个 script 标签, 然后添加到页面上, 这样当我们点击 button 按钮就会发送一个跨域请求, 而且还是允许的.
Demo1 项目 index.html 页面上添加 JS 代码:
- function get_ele_script(url){
- var ele_script=$('<script>');
- ele_script.attr('src',url);
- ele_script.attr('id','ele_script');
- $('body').append(ele_script);
- $('#ele_script').remove()
- }
- $('.cli').click(function () {
- get_ele_script('http://127.0.0.1:8001/ajax/')
- })
这样就成功用点击事件发送了一个跨域请求, 在 Demo2 的视图中, 有返回值, 但如果我不定义返回的值, HTML 文件就会报没有定义的错误, 而且视图返回的值在前端页面是以变量的形式显示.
Demo2 项目的视图:
- def Ajax(request):
- dic={'name':'zhnag','age':46}
- dic_json=JSON.dumps(dic)
- return HttpResponse('f(%s)'%dic_json)
此时, 我们就应该在 HTML 文件中定义 f()
- function f(params) {
- console.log(params);
- console.log(typeof params);
- }
这样, 当我们点击 button 时, 会往 Demo2 发送一个请求, Demo2 会返回带参数的 f(), 由于已经定义了 f()函数, 所以当返回时会执行这个函数, 这种方法就实现了发送跨域请求, 然后接受返回值, 并对返回值进行处理.
2, 版本 2
其实版本 1 在 Demo2 项目中把返回的函数名写死了, 如果照版本 1, 所有来反问 Demo2 的浏览器都会得到一个叫 f()的函数, 我们在声明的时候也只能写成 f(). 其实我们可以这样在请求的时候把我们定义的函数名一起发过去, 让他就给我返回我发送过去的函数, 这样, 我们定义函数名就可以随意了.
Demo1 项目的 index.HTML 页面上就应这样写:
- function f(params) {
- console.log(params);
- console.log(typeof params);
- }
- $('.cli').click(function () {
- get_ele_script('http://127.0.0.1:8001/ajax/?callbacks=f')
Demo2 项目的视图:
- def Ajax(request):
- a=request.GET.get('callbacks')
- dic={'name':'zhnag','age':46}
- dic_json=JSON.dumps(dic)
- return HttpResponse('%s(%s)'%(a,dic_json))
3, 版本 3
上面两个版本就没有基于 Ajax 请求, 这个版本就基于 Ajax 发送跨域请求.
Demo1 项目下的 index.HTML 页面上:
- function f(params) {
- console.log(params);
- console.log(typeof params);
- }
- $('.cli').click(function () {
- $.Ajax({
- url:'http://127.0.0.1:8001/ajax/callbacks=f',
- type:'GET',
- dataType:'jsonp',
- })
- })
Demo2 项目的视图:
- def Ajax(request):
- a=request.GET.get('callbacks')
- dic={'name':'zhnag','age':46}
- dic_json=JSON.dumps(dic)
- print(type(dic_json))
- return HttpResponse('%s(%s)'%(a,dic_json))
4, 版本 4
这也是基于 Ajax 发送的跨域请求, 只是比上一版本更简单.
Demo1 项目下的 index.HTML:
- function f(params) {
- console.log(params);
- console.log(typeof params);
- }
- $('.cli').click(function () {
- $.Ajax({
- url:'http://127.0.0.1:8001/ajax/',
- type:'GET',
- dataType:'jsonp',
- JSONP:'callbacks',
- jsonpCallback:'f'
- })
- })
Demo2 项目的视图:
- def Ajax(request):
- a=request.GET.get('callbacks')
- dic={'name':'zhnag','age':46}
- dic_json=JSON.dumps(dic)
- print(type(dic_json))
- return HttpResponse('%s(%s)'%(a,dic_json))
5, 版本 5(终极版本)
基于 Ajax 的跨域请求, 并把返回值给 Ajax 的 success.
Demo1 项目下的 index.HTML:
- $('.cli').click(function () {
- $.Ajax({
- url:'http://127.0.0.1:8001/ajax/',
- type:'GET',
- dataType:'jsonp',
- JSONP:'callbacks',
- success:function (data) {
- console.log(data)
- }
- })
- })
Demo2 项目下的视图:
- def Ajax(request):
- a=request.GET.get('callbacks')
- dic={'name':'zhnag','age':46}
- dic_json=JSON.dumps(dic)
- return HttpResponse('%s(%s)'%(a,dic_json))
这个版本就比较简单, 书写方便
四, 基于 CORS 的 Ajax 跨域请求
最开始, 我们讲的报错是: CORS 头少:'Access-Control-Allow-Origin', 既然少一个, 我们就加一个, 就可以了, 其实这种方式才是最常用.
Demo1 项目下的 index.HTML:
- $('.cli').click(function () {
- $.Ajax({
- url:'http://127.0.0.1:8001/ajax/',
- type:'get',
- data:{'a':1},
- success:function (res) {
- console.log(res)
- }
- })
- })
Demo2 项目下的视图:
- def Ajax(request):
- dic = {'name': 'zhnag', 'age': 46}
- http=HttpResponse(JSON.dumps(dic))
- http['Access-Control-Allow-Origin']='http://127.0.0.1:8000' #这相当于加了一个白名单, 对于'http://127.0.01:8000'的跨域请求就允许通行
- return http
来源: https://www.cnblogs.com/12345huangchun/p/10339812.html