Web编程 Ajax,跨域,XSS攻击

一.Ajax
详情参见:https://www.cnblogs.com/wupeiqi/articles/5703697.html

1.简介:

Ajax即Asynchronous Javascript And XML(异步JS与XML),是1种创建交互式网页应用的网页开发技术方案
字面意思是使用JS与Server进行异步交互,传输XML数据(不过实际上不一定是XML,现在用的更多的是JSON)

异步JS:使用[JS]以及[浏览器提供的类库]向Server发送请求,Server处理完请求后,自动执行某个JS回调函数
  说明:以上请求和响应的整个过程是"偷偷"进行的,页面上无任何感知
XML:是1种标记语言,是Ajax在和后台交互时传输数据的格式之一

同步交互:发送1个请求,就要等待Server的响应结束,然后才能发送第2请求
异步交互:发送1个请求后,无需等待Server响应,就可以发送第2个请求

对于Web应用,Client Browser发送请求,Server接收并处理请求,然后返回结果
返回的常常是str(HTML),Browser将str(HTML)渲染并显示到浏览器上
对传统的Web应用来说,完成任何1个简单操作都需要重新加载全局数据
而使用Ajax发送请求,具有以下特点:
1.使用JS向Server发送异步请求
2.浏览器页面局部刷新(给用户的感受是在不知不觉中完成请求和响应)

场景示例:
1.注册时,输入用户名,检测用户名是否已被注册
2.登录验证,提示用户名/密码错误(见下图)
3.删除数据行时,将行ID发送到后台,后台在数据库中删除
成功后,在页面DOM中将数据行也删除(博客园)

在这里插入图片描述
2.原生Ajax(XmlHttpRequest对象):

Ajax主要使用[XmlHttpRequest]对象来完成请求,该对象在主流浏览器中均存在(除早期IE)
Ajax首次出现IE5.5中存在(ActiveX控件)

<body>
	<div>
	    <a onclick="AjaxSubmit1">GET</a>
	    <a onclick="AjaxSubmit2">POST</a>
	<div>
	<script>
	    function AjaxSubmit1() {
	        var xhr=new XMLHttpRequest();//创建1个XmlHttpRequest对象的实例
	        xhr.onreadystatechange=function () {
	            if (xhr.readyState==4) {
	                console.log(xhr.responseText);//返回的文本信息
	            };//表示"已接收到全部响应数据",相当于回调函数;必须在.send()之前设置
	        };//状态变化时执行对应函数;需要在相应操作执行前设置(例:见上1行)
	        xhr.open("GET","/ajax.html?p=123");//创建1个连接(此时还未发送请求)
	        xhr.send(null);//发送请求;null表示请求体里没有数据
	    }
	    function AjaxSubmit2() {
	        var xhr=new XMLHttpRequest();//创建1个XmlHttpRequest对象的实例
	        xhr.onreadystatechange=function () {
	            if (xhr.readyState==4) {
	                console.log(xhr.responseText);//返回的文本信息
	            };//表示"已接收到全部响应数据",相当于回调函数;必须在.send()之前设置
	        };//状态变化时执行对应函数;需要在相应操作执行前设置(例:见上1行)
	        xhr.open("POST","/ajax.html");//创建1个连接(此时还未发送请求)
	        xhr.setRequestHeader("Content-Type"."application/x-www-form-urlencoded; charset-UTR-8");
	          //需要该请求头,否则Django不会将数据从req.body中解析到req.POST中去
	        xhr.send("p=456");//发送请求;参数是要以POST方式发送的数据
	    }
	</script>
</body>

3.基于JQuery的Ajax实现:
error参见:https://blog.csdn.net/u014756827/article/details/52950514
success与complete的区别参见:https://www.cnblogs.com/alice-you/p/7928099.html
dataType参见:https://blog.csdn.net/w4187402/article/details/90482696
traditional参见:https://www.cnblogs.com/hxw6/p/9718149.html

JQuery其实就是1个JS的类库,对JS做了封装,使开发者可在其基础上用更少代码实现更多功能
JQuery不产生Ajax,只是做了封装,JQuery Ajax的本质还是XMLHttpRequest/ActiveXObject

<button class="send_Ajax">send_Ajax</button>
<script>
    $(".send_Ajax").click(function() {
    //下面开始是基于JQuery的Ajax实现:///
        $.ajax({
            url:"/handle_Ajax/",//指定提交到哪
            //???是不是可以自己把GET形式的数据放进来???
            
            type:"POST",//指定请求方式
            
            data:{"username":"Yuan","password":123},//指定要提交的数据
            //data:{"k":["v11","v12"]}//此时应设置traditional为True
            //str的""可省略
            //如果是POST,数据放在请求体;如果是GET,数据放在请求头(自动拼接进去)
            //data中只支持num/str/list,不能再包含dict
            //如果需要保护dict,需用JSON.stringify()转换成str
            
            dataType:"JSON",
            //声明arg的数据类型;Django会按该类型把arg处理成纯文本类型
            //如为"JSON",会对arg进行反序列化;为"text"(默认值),不对arg进行任何处理
            //还可为"html"/"xml"/"jsonp"/"script"
            
            traditional:false,
            //如果data中嵌套有list,应设置本参数为true,默认为false

            success:function(arg) {
            //arg是Server返回的数据
            //由于指定了dataType为JSON,data是对象而非str
                window.location.reload();
                //通过JS主动刷新页面
            },//回调函数:在请求成功时执行时执行
            
            error:function(jqXHR,textStatus,err) {
            //jqXHR是1个jqXHR对象(Jquery1.4及之前版本是XMLHttpRequest对象),包括XMLHttpRequest对象和其他属性/信息
            //textStatus表示返回的状态,为str
            //err表示服务器返回的错误信息,为str
                console.log(arguments);
            },//用于对错误信息进行处理
            
            complete:function(jqXHR,textStatus) {
                console.log(textStatus);
            },//在请求完成时执行
            
            statusCode:{
                '403':function(jqXHR,textStatus,err) {
                    console.log(arguments);
                },
                '400':function (jqXHR,textStatus,err) 
                    console.log(arguments);
                }
            }
        })
    })
</script>

4.Ajax流程:
基本流程参见:https://blog.csdn.net/linzhaojie525/article/details/55278829

流程图来自:https://www.cnblogs.com/hongfei/archive/2011/11/28/ajax_process.html
在这里插入图片描述
5.使用< iframe>"伪造"Ajax:

<iframe>具有局部加载内容的特性,因此可以使用其来伪造Ajax请求,不刷新页面
相当于<iframe>提供了1条传输数据的通道
这是兼容性最好的Ajax提交方式

<iframe id="iframe" name="ifra"<!-- οnlοad="reloadIframe(this);"-->></iframe>
  <!--默认<iframe>中会显示view函数返回的数据-->
  <!--onload参数指定的函数会在加载完成后执行(每次接收到数据,<iframe>都需要重新加载)-->
<form id="fm" action="/ajax.html" method="POST" target="ifra">
  <!--target属性指定通过name="ifra"的<iframe>发送数据-->
    <input name="root" value="111111">
    <a onclick="Submit()">提交</a>
</form>
<script src="/static/js/jquery-3.1.1.js"></script>
<script>
    function reloadIframe() {//相当于回调函数
        console.log(this);//输出:<iframe>
        console.log(this.contentWindow);//输出:放在<iframe>中的那个窗口
        console.log(this.contentWindow.document);//输出:上述窗口的HTML文档信息
        console.log(this.contentWindow.document.body);//输出:上述窗口中的<body>
        var c=this.contentWindow.document.body.innerHTML;
        var obj=JSON.parse(c);
    }//由于代码从上到下被解析,第1次加载<iframe>时<iframe>找不到该函数,所以不直接绑定给<iframe>
    function Submit() {//绑定回调函数并提交数据
        document.getElementById("iframe").onload=reloadIframe;
          //通过这种方式绑定,内部的this就是当前标签,不需要手动传入
          //但如果直接绑定给<iframe>,内部的this是窗口对象,就需要手动传入this
        document.getElementById("fm").submit();
    }
</script>

6.Ajax与序列化:

success函数的参数是Server返回的数据,默认为str,可通过反序列化得到对象形式的返回数据
也可以指定dataType参数为"JSON",这样success函数的参数就是对象而非str

<str>=JSON.stringify(<data>):将对象转换成JSON字符串(序列化)
  相当于Python中的json.dumps()
<data>=JSON.parse(<str>):JSON字符串转换成对象(反序列化)
  相当于Python中的json.loads()

//实例:
$.ajax({
    ...
    //dataType:"JSON",
    success:function(data) {
        data_obj=JSON.parse(data)
        ...
    },
    ...

二.使用Ajax上传文件
参见:https://blog.csdn.net/weixin_46131409/article/details/107163959

三.实现跨域
1.同源策略:

之前的示例都是向本地发送请求,但如果向非本地的Server发送请求,会出现问题(报错见下图)
Browser存在同源(IP+Port)策略机制,不允许从1个源加载的文档/脚本获取/设置从另1个源加载的文档的属性
这个策略是Browser的,因此Server收到了请求,也返回了数据,但数据会被Browser禁用并丢弃

在这里插入图片描述
2.通过JSONP实现跨域请求:

同源策略并不制约所有请求,XMLHttpRequest遵循该策略,但<img><iframe><script>等具有src属性的标签不遵循
JSONP(JSON with Padding)是JSON的1种"使用模式",可利用<script>的src属性实现跨域
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <div id="content"></div>
    <input type="button" onclick="Jsonp1();"  value='提交'>
    <input type="button" onclick="Jsonp2();" value='提交'>
    <script type="text/javascript" src="/static/js/jquery-3.1.1.js"></script>
    <script>
        function Jsonp1() {//自己实现
            var tag=document.createElement("script");//设置1个<script>
            tag.src="http://127.0.0.1:9090/test";
              //设置src属性(要访问的资源的地址)
            document.head.appendChild(tag);//添加<script>
              //<script>相当于1个JS文件,加载时会向src发送请求
              //返回的数据会被放在里面,所以返回的数据需要遵循JS的语法
            document.head.removeChild(tag);//移除<script>
              //可以立即删除,也可以在得到返回值后删除(Ajax采用后1种)
        }
        function Jsonp2() {//使用JQuery中已经写好的(具体实现和Jsonp1()相同)
            $.ajax({
                //url:"http://127.0.0.1:9090/test2",
                type:"GET",//JSONP的形式只能发送GET请求(因为是发送URL,本身就是GET形式)
                  //如果设为POST,会自动改为GET
                dataType:"JSONP",//小写("jsonp")也可以
                jsonp:"callback",
                jsonpCallback:"list",//这2句相当于设置callback=list
                  //callback参数表示要求以指定的函数包裹返回的数据(有些网站不遵循)
                  //一定要这么写,不能放在地址栏里,否则会出错
                //success:function(data,statusText,xmlHttpRequest){
                //  //data是返回的数据
                //    console.log(data);
                //}
            })
        }
        function do(arg) {//类似于回调函数
            $("#content").html(arg);
        }
        function list(arg) {
            console.log(arg);
        }
    </script>
</body>
</html>

<!--可以使用http://jxntv.cn/data/jmd-jxtv2.html进行测试,回调函数是list()
    注意:这个网址用不了callback参数,只能用list()   凸(艹皿艹 )-->
#views.py:

from django.shortcuts import HttpResponse

def test(req):
    return HttpResponse("do('测试跨域');")#在Client执行list()
      #由于返回的数据会被放到JS文件里,需要遵循JS的格式
      #这样写,在Client中定义好函数就可以完成对返回的数据的处理

def test2(req):
    name=req.GET.get("callback")
    return HttpResponse("%s('跨域测试');"%name)
      #使用callback参数指定的函数包裹要返回的数据

3.CORS(Cross-Origin Resource Sharing;跨站资源共享):

随着技术的发展,现在的Browser可以支持主动设置从而允许跨域请求
即CORS,其本质是同时返回响应头,使Browser允许跨域请求
而且通过该方式既可以发送GET请求,也可以发送POST请求

四.XSS攻击
参见:https://www.cnblogs.com/tugenhua0707/p/10909284.html
1.概念:

XSS攻击(Cross Site Scripting;跨站脚本攻击):
指利用网页开发时留下的漏洞,注入恶意script代码到网页
当用户浏览该页面时,这些嵌入到网页的script代码会执行
从而达到恶意攻击者的目的,如获取COOKIE

2.实例:

把以下代码发送到CSDN的评论区,如果CSDN没有采取相关措施,以下代码就会被执行
如果发生了这样的事,所有用户在访问该页面时都会收到大量弹出框,而这显然是不合适的
更危险的是,可通过类似的代码获取本地存储的COOKIE并发送出去,这样用户身份就可能被伪造

<script>
    for(var i=0;i<9999;i++) {
        alert(i)
    }
</script>

3.防御方法:

1.浏览器默认不执行发送到页面的代码,而将其当作普通的文本进行渲染
2.对用户上传的数据,不使用JQuery中的safe过滤器;自己发送的代码,可以用safe过滤器
  //关于safe过滤器:参见 Django框架 模板.二.1.(4) 部分
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值