一.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) 部分