1、django之博客-实现评论、XSS攻击防护,2、在kindedit中实现图片预览
评论实现:
最终要获取后端传来的评论结果: <script> $.ajax({
url:'/content',
type:"GET",
dataType:'JSON',
success:functaion(arg){
if (arg){
var comment=commentTree(arg.data);
$('#commentArea').append(comment);
}else{
alter(arg.msg)
}
}
}); // 自定义方法format String.prototype.Format=function (arg) { /* console.log(this,arg)//this 就是asf(当前字符串), arg是参数(Format方法传入的参数 ) 例如有一个字符串是这样: this 就是 " i am {name} ,age {age} arg 就是 '{name} {age}' return 111; 格式化之后获取的新内容 */ var temp=this.replace(/\{(\w+)\}/g,function (k,kk) { /* k 匹配到的是 {asf},然后kk再对上一次进行匹配得到的是asf,然后arg字典返回了一个,=*/ return arg[kk]; }); return temp; }; v='{asf}'; v.Format; function commentTree(commentList) { /* * commentList 是上面通过ajax 从后端获取的评论结果, * * */ var comment_str="<div class='comment'>'"; $.each( commentList,function (k,row) { var temp="<div class='content'{content}</div>".Format({content:row.content}) comment_str+=temp; if (row.child.length()>0){ comment_str+=commentTree(row.child); } } ) }
附录:自定义字符串格式化详解:
XSS攻击防护:
BeautifulSoup 库,过滤掉script标签,与form表单配合使用
详细查看:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html
xss.py :#封装在utils 下
from bs4 import BeautifulSoup #BeautifulSoup 是一个可以从XML、HTML中提取数据的PYTHON库,帮助开发者节省时间 。 #https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html def xss(comment_content): # 白名单,没有恶意的script 标签 valid_tag={ 'p':['class','id'], 'img':['src'], 'div':['class'], 'title':['class'], } soup=BeautifulSoup(comment_content,'html.parser') #初始化一个BS对象,还有另一个方法,soup = BeautifulSoup(comment_content,'html.parser') tags=soup.find_all()#拿到当前所有的节点(也就是所有的标签),是一个HTML对象包着很多的标签对象。find_all()里可以指定参数 # print(tags) for tag in tags:#进入到HTML对象里,拿到每一个标签对象 if tag.name not in valid_tag: #tag.name 是标签名 #print(tag.name) tag.decompose() #decompose方法将当前节点移除文档树并完全销毁:----就是干死了 if tag.attrs:# 有 属性的标签 for k in list(tag.attrs.keys()):#{'class': ['sister'], 'href': 'http://example.com/elsie', 'id': 'link1'} if k not in valid_tag[tag.name]: del tag.attrs[k] content_str=soup.decode()#可以调用 encode() 方法获得字节码或调用 decode() 方法获得Unicode. return content_str html_doc = """ <head><title class='abc'>The Dormouse's story</title></head> <p class="abc" id='p1'><b>The Dormouse's story</b></p> <p class="story" id='2'>Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <script>alter(123)</script> <p class="story">...</p> """ xss(html_doc)
form.py
def CommentForm(Form): title=fields.CharField(max_length=128) content=fields.CharField(widget=widgets.Textarea(attrs={'id':'i1'})) def clean_content(self): user_content=self.cleaned_data['content'] from utils.xss import xss#导入xss return xss(user_content)#将数据传给xss 过滤,有script 的将它过滤出来
views.py
from app01.forms import CommentForm CONTENT='' # 发布评论内容 def publish(request): if request.method=='GET': obj=CommentForm() return render(request,'publish.html',{'obj':obj}) else: obj=CommentForm(request.POST) if obj.is_valid(): print(obj.cleaned_data) content=obj.cleaned_data['content'] global CONTENT CONTENT=content print(content) return HttpResponse('....')
def see(request): #查看上传文章 的结果
return render(request,'see.html',{'con':CONTENT})
###see.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {{ con|safe }} </body> </html>
前端publish.html页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/publish/" method="POST" novalidate> {% csrf_token %} <p> 文章标题: {{ obj.title }} </p> <div> <div>文章内容</div> {{ obj.content }} </div> <!--<textarea name="content" id="i1" cols="30" rows="10">--> <!--</textarea>--> <input type="submit" value="submit"> </form> <script src="/static/kindeditor-4.1.10/kindeditor-all.js"></script>//导入kindeditor, <script>
KindEditor.create('#i1',{ width:'700px', height:'500px', // 控制显示的工具 items:[ 'source', '|', 'undo', 'redo', '|', 'preview', 'print', 'template', 'code', 'cut', 'copy', 'paste', 'plainpaste', 'wordpaste', '|', 'justifyleft', 'justifycenter', 'justifyright', 'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript', 'superscript', 'clearhtml', 'quickformat', 'selectall', '|', 'fullscreen', '/', 'formatblock', 'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold', 'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat', '|', 'image', 'multiimage', 'flash', 'media', 'insertfile', 'table', 'hr', 'emoticons', 'baidumap', 'pagebreak', 'anchor', 'link', 'unlink', '|', 'about' ], // 显示出来的工具,但是不让用,显示灰色 // noDisableItems:['undo','redo'], // designMode:false, // 评论里面的上传文件--------这里是上传图片 uploadJson:'/upload_img',//对应的url,看《附录》 extraFileUploadParams:{ 'csrfmiddlewaretoken':'{{ csrf_token }}' } } ) </script> </body> </html>
测试:
查看结果:script 没有发挥作用,拦截有效
《附录》
图片的上传:
前端上传代码:
<form method="POST" action="/wangzhe.html" novalidate> {% csrf_token %} <p> 文章标题 {{ obj.title }} </p> <div> <div>文章内容</div> <div> {{ obj.content }} </div> </div> <input type="submit" value="提交" /> </form> <script src="/static/kindeditor-4.1.10/kindeditor-all.js"></script> <script> KindEditor.create("#i1",{ width: "700px", height: "300px", resizeType:1, uploadJson: '/upload_img.html', extraFileUploadParams:{ "csrfmiddlewaretoken":"{{ csrf_token }}" } }) </script>
views.py对应的处理函数 :
def upload_img(request): import os # 判断上传的类型文件 upload_type=request.POST.get('dir') # 还需要再做下一步判断 file_obj=request.FILES.get('imgFile') #kindedit 的提交时,它的内部就是ifram + from 表单,伪AJAX的提交,而且这个文件只能叫imgFile----> 实际就是input type='file' name='imgIlf ,'要是改这个名字的话需要在前端添加filePostName:'fafa',那这里就要获取fafa了,参考:编辑器初始化参数http://kindeditor.net/docs/option.html file_path=os.path.join('static/img/',file_obj.name) with open(file_path,'wb') as f: for chunk in file_obj.chunks(): f.write(chunk) # 返回的数据只能是这几个KEY, dic = { 'error': 0, 'url': '/'+file_path,#图像文件的路径,这样就能在前端预览了。 'message': '错误了...' } import json return HttpResponse(json.dumps(dic)) print(request.POST,request.FILES)
查看结果:
在输入文章的框 中预览:
附:
《自定义字符串方法》
1、
2、
3、前端的正则匹配
4、加上g,#glob 全部替换
5、有第二个参数 :,参数拿到的是匹配正则的
6、
再加个kk,拿到的就是没有大括号的 值
如
:k={name} 等于的是加上括号的值
kk=name 等于的是没有括号的值