Ajax跨域请求

摘要:
在以下示例中,通过Ajax访问自己的页面没有问题:示例:前端代码后端代码结果:2。跨域所谓的跨域是指请求不是本地url。有关具体示例,请参见:现在通过项目1中的Ajax访问项目2的页面:单击按钮发现它没有返回到我们希望看到的内容,问题出在哪一步?在项目2的背景中,我们可以看到接待被阻止了。查看Firefox的首页:问题显然已被阻止。为什么?

一、同源策略

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,

如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。

可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。

所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,

即检查是否同源,只有和百度同源的脚本才会被执行,如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
 
在下面的实例中,通过Ajax访问自己的页面没有问题:
实例:
Ajax跨域请求第1张前端代码
Ajax跨域请求第2张后端代码

结果:

Ajax跨域请求第3张

二、跨域

所谓的跨域就是请求的并不是本地url,具体实例请看:

 现在在项目1通过ajax访问项目2的页面(8001访问8002):

Ajax跨域请求第4张

点击按钮发现并没有返回我们希望看到的,那到底是哪一步出现了问题了:

在项目2的后台,我们看到:

Ajax跨域请求第5张

证明了已经处理了,难道是接收被拦截了,在火狐查看前端页面:

Ajax跨域请求第6张

问题很明显就是被拦截了,为什么被拦截了?我只能说这是一种安全措施,这是在浏览器设计之初就已经规定好的,一直延续至今。

 

三、跨域的解决方法

在实际工作中,由于在大互联网时代,各行各业分工十分细化,单就大数据而言,

有些公司专门做数据收集、有些公司只做数据处理、而有些只做销售,这些公司传输数据的手段就是跨域请求。

下面会讲解三种解决跨域的方法:

1.借助script标签实现跨域

我们常用的Jquery可以这样:

<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

在项目启动进行加载的时候,就会去对应的服务器取数据,利用这种特性可以实现跨域请求:

Ajax跨域请求第7张

返回一个func(),这样在前端:

Ajax跨域请求第8张

最后就能打印其中的数据了。

如果把需要传递的数据放在括号里面,就能把它取出来了,这样就可以达到跨域请求的目的了。

为了达到数据的丰富性,我们可以先进行序列化。

最后实现的代码详解:

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
    <script src="/static/jquery-3.2.1.min.js"></script>
</head>
<body>
<h3>这是项目1</h3>
<button class="b1">send a ajax</button>

{% csrf_token %}

<script>
    function func(s) {
        console.log(s)
    }
    
    function cross_domain(url) {
{#        定义一个标签,添加一个url元素,将其添加到body里面#}
{#        为了不每次点击都会加载一个script标签,每次加载之后就删除#}
        var $ele_script = $("<script>");
        $ele_script.attr("src",url);
        $ele_script.attr("class","cs");
        $("body").append($ele_script);
        $(".cs").remove()
    }

{#    点击按钮的时候就会触发,此时才会加载<script>#}
{#    使用callback=func可以将后端传输字符串进行解耦,在后端可以接收callback,这样再传递func()到前端#}
    $(".b1").click(function () {
        cross_domain("http://127.0.0.1:8002/ajax_send/?callback=func")
    })

</script>
</body>
</html>

后端代码:

from django.shortcuts import render,HttpResponse

def index(request):

    return render(request,"index.html")

import json
def ajax_send(request):
    dict = {"name":"kebi"}
    func =request.GET.get("callback")  #这样可以不用固定函数名
    return  HttpResponse("%s(%s)"%(func,json.dumps(dict)))

这其实就是JSONP的简单实现模式,或者说是JSONP的原型:创建一个回调函数,

然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。

jsonp是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略。

将JSON数据填充进回调函数,这就是JSONP的JSON+Padding的含义。

一般情况下,我们希望这个script标签能够动态的调用,而不是像上面因为固定在html里面所以没等页面显示就执行了,很不灵活。

我们可以通过javascript动态的创建script标签,这样我们就可以灵活调用远程服务了。

2.jQuery对JSONP的实现

(1)getJSON

jQuery框架也当然支持JSONP,可以使用$.getJSON(url,[data],[callback])方法:

项目一前端部分:

<script>
    $(".b1").click(function () {
        $.getJSON("http://127.0.0.1:8002/ajax_send/?callback=?",function (data) {
{#            callback=?这个值系统会帮你随机生成,就相当于让面的ross_domain#}
{#            当拿到结果之后,只会执行function ()这个匿名函数#}
            console.log(data)
        })
    })
</script>

项目二后端部分:

import json
def ajax_send(request):
    dict = {"name":"kebi"}
    func =request.GET.get("callback")
    print("func",func)  #func jQuery3210924015436172589_1519900847362
    print("项目2.。。")
    return  HttpResponse("%s(%s)"%(func,json.dumps(dict)))

经过测试可以知道,这种方法也是可以的,其实就是对script的封装。

结果是一样的,要注意的是在url的后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,

callback后面的那个问号是内部自动生成的一个回调函数名。

此外,如果说我们想指定自己的回调函数名,或者说服务上规定了固定回调函数名该怎么办呢?我们可以使用$.ajax方法来实现

(2)$.ajax

看到这个有些人就疑惑,这个不就是Ajax吗,不是说ajax不行吗,这咋就又行了?

其实确实不行,只是Jquery的作者让它和ajax同名而已。

项目一前端:

<script>
$(".b1").click(function () {

   $.ajax({
       url:'http://127.0.0.1:8002/ajax_send/',
       dataType:"jsonp",   {# 期待数据类型,一定要加,只要有这句话,就会去添加script标签 #}
       jsonp: 'callback',  {# 其实就是补充在后面:http://127.0.0.1:8002/ajax_send/?callback=SayHi#}
       jsonpCallback:"SayHi"  {# 如果这里不加jsonpCallback,就会是callback=?,这样就是getJson #}
   });
});

function SayHi(data) {
    console.log(data)
}
</script>

项目二后端:

def ajax_send(request):
    dict = {"name":"kebi"}
    func =request.GET.get("callback")
    print("func",func)  #func SayHi
    print("项目2.。。")
    return  HttpResponse("%s(%s)"%(func,json.dumps(dict)))

当然,最简单的形式还是通过回调函数来处理(推荐):

<script>
$(".b1").click(function () {

   $.ajax({
       url:'http://127.0.0.1:8002/ajax_send/',
       dataType:"jsonp",   
       jsonp: 'callback', 
       success:function (data) {
           console.log(data)
       }
   });
});
</script>

 jsonp: 'callbacks'就是定义一个存放回调函数的键,jsonpCallback是前端定义好的回调函数方法名'SayHi',

server端接受callback键对应值后就可以在其中填充数据打包返回了; 

jsonpCallback参数可以不定义,jquery会自动定义一个随机名发过去,那前端就得用回调函数来处理对应数据了。

利用jQuery可以很方便的实现JSONP来进行跨域访问。

  

注意:JSONP一定是GET请求

最后来一个跨域请求的实例:

Ajax跨域请求第9张Ajax跨域请求第10张
<input type="button" onclick="AjaxRequest()" value="跨域Ajax" />


<div id="container"></div>


    <script type="text/javascript">
        function AjaxRequest() {
            $.ajax({
                url: 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403',
                type: 'GET',
                dataType: 'jsonp',
                jsonp: 'callback',
                jsonpCallback: 'list',
                success: function (data) {

                    $.each(data.data,function(i){    {# 循环 #}
                        var item = data.data[i];
                        var str = "<p>"+ item.week +"</p>";   {# 添加日期标签 #}
                        $('#container').append(str);
                        $.each(item.list,function(j){   {# 循环 #}
                            var temp = "<a href='http://t.zoukankan.com/" + item.list[j].link +"'>" + item.list[j].name +" </a><br/>";
                            $('#container').append(temp);
                        });
                        $('#container').append("<hr/>");
                    })

                }
            });
        }
</script>
跨域请求

免责声明:文章转载自《Ajax跨域请求》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇前端开发中常遇到的浏览器兼容问题小结js forEach参数详解,forEach与for循环区别,forEach中如何删除数组元素下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

CORS跨域实现思路及相关解决方案

本篇包括以下内容: CORS 定义 CORS 对比 JSONP CORS,BROWSER支持情况 主要用途 Ajax请求跨域资源的异常 CORS 实现思路 安全说明 CORS 几种解决方案 自定义CORSFilter Nginx 配置支持Ajax跨域 支持多域名配置的CORS Filter keyword:cors,跨域,ajax,403,fi...

JAVA框架-前后端分离(Json和ajax)

为什么要前后端分离? 在以前的学习代码中,可以看出来我们在jsp页面页面上也通过EL表达式和jstl写了很多的java程序,这实际上在前端的页面中混入了很多后端的逻辑,这就是传统的web开发。在传统的web开发中,页面展示的内容以及页面之间的跳转逻辑,全都由后台来控制,这导致了前后端耦合度非常高,耦合度高则意味着,扩展性差,维护性差,等等问题 传统开发的问...

Vue-cli 创建的项目配置跨域请求(通过反向代理)---配置多个代理--axios请求

问题描述: 使用 Vue-cli 创建的项目,开发地址是 localhost:8080,需要访问 localhost:9000或https://m.maoyan.com或http://image.baidu.com上的接口 分析原因: 不同域名之间的访问,需要跨域才能正确请求。跨域的方法很多,通常都需要后台配置 不过 Vue-cli 创建的项目,可以直接...

c语言处理通过ajax发起http的post请求CGI并向浏览器返会值

环境:centos 6.5 web容器:apache2.4,[<http://httpd.apache.org/docs/2.4/] 准备: cd /usr/local/httpd-2.4.20/modules/generators enter   cp mod_cgi.c /usr/local/apache/bin enter   ....

Java大文件分片上传/多线程上传组件

javaweb上传文件 上传文件的jsp中的部分 上传文件同样可以使用form表单向后端发请求,也可以使用 ajax向后端发请求     1. 通过form表单向后端发送请求          <form id="postForm" action="${pageContext.request.contextPath}/UploadServlet" m...

Nodejs开发指南-笔记

第三章 异步式I/O与事件编程3.1 npm install -g supervisor  supervisor app.js 当后台修改代码后,服务器自动重启,生效修改的代码,不用手动停止/启动3.2 单线程异步I/O  减少了多线程的开销,对于操作系统,创建线程的开销很大,需分配内存、列入调度。同时线程切换时  需要内存换页,CPU的缓存被清空,切换回...