8 功能6:后台管理页面,编辑文章,xss攻击
1、后台管理页面之文本编辑
# 后台管理url re_path(r'^cn_backend/$', views.cn_backend, name='cn_backend'), re_path(r'^cn_backend/add_article/$', views.add_article, name='add_articles'),
view视图
from django.shortcuts import render, HttpResponse, redirect from blog import models from django.contrib.auth.decorators import login_required # 用户登录证装饰器 @login_required def cn_backend(request): """后台管理页面""" article_list = models.Article.objects.filter(user=request.user) return render(request, "backend/backend.html", locals()) @login_required def add_article(request): if request.method == "POST": title = request.POST.get('title') content = request.POST.get('content') models.Article.objects.create(title=title,content=content, user=request.user) return redirect("/cn_backend/") return render(request, "backend/add_article.html", locals())
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap3/css/bootstrap.css"> <style type="text/css"> .glyphicon-comment { vertical-align: -1px; } </style> </head> <body> <div class="site-header"> <nav class="navbar navbar-inverse"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="#"> 后台管理 </a> </div> </div> </nav> </div> <div class="site-body"> <div class="container-fluid"> <div class="row"> <div class="col-md-2 col-lg-offset-1"> <div class="panel panel-default"> <div class="panel-heading">操作</div> <div class="panel-body"> <a href="/cn_backend/add_article/">添加文章</a> </div> </div> </div> <div class="col-md-8"> <div> <ul class="nav nav-tabs"> <li role="presentation" class="active"><a href="#">文章</a></li> <li role="presentation"><a href="#">日记</a></li> <li role="presentation"><a href="#">随笔</a></li> <li role="presentation"><a href="#">相册</a></li> </ul> </div> <div class="tab-content"> <div class="article_list small"> <table class="table table-hover table-striped"> <thead> <th>标题</th> <th>评论数</th> <th>点赞数</th> <th>操作</th> <th>操作</th> </thead> <tbody> {% for article in article_list %} <tr> <td>{{ article.title }}</td> <td>{{ article.comment_count }}</td> <td>{{ article.up_count }}</td> <td><a href="">编辑</a></td> <td><a href="">删除</a></td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </div> </div> </div> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap3/css/bootstrap.css"> <style type="text/css"> .glyphicon-comment { vertical-align: -1px; } </style> </head> <body> <div class="site-header"> <nav class="navbar navbar-inverse"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="/cn_backend/"> 后台管理 </a> </div> </div> </nav> </div> <div class="site-body"> <div class="container-fluid"> <div class="row"> <div class="col-md-2 col-lg-offset-1"> <div class="panel panel-default"> <div class="panel-heading">操作</div> <div class="panel-body"> <a href="/cn_backend/add_article/">添加文章</a> </div> </div> </div> <div class="col-md-8"> <div> <ul class="nav nav-tabs"> <li role="presentation" class="active"><a href="#">文章</a></li> <li role="presentation"><a href="#">日记</a></li> <li role="presentation"><a href="#">随笔</a></li> <li role="presentation"><a href="#">相册</a></li> </ul> </div> <div> <form action="" method="post"> {% csrf_token %} <div class="add_article"> <div class="alert-danger text-center">添加文章</div> <div class="add_article_region"> <div class="title form-group"> <label for="">标题</label> <div> <input type="text" name="title"> </div> </div> <div class="content form-group"> <label for="">内容(Kindeditor编辑器,不支持拖放/粘贴上传图片) </label> <div> <textarea name="content" id="article_content" cols="30" rows="10"></textarea> </div> </div> <input type="submit" class="btn btn-default"> </div> </div> </form> </div> </div> </div> </div> </div> </body> </html>
2、富文本编辑框KindEditor
1、编辑器的引入
官网 http://kindeditor.net/demo.php
-
在需要显示编辑器的位置添加textarea输入框。
<textarea id="editor_id" name="content" style="width:700px;height:300px;"> <strong>HTML内容</strong> </textarea>
-
在该HTML页面添加以下脚本。
2、参数设置
<script> KindEditor.ready(function (K) { window.editor = K.create('#editor_id', { width: "800", height: "600", 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' ], resizeType:1 }); }); </script>
3、上传功能
1)如何上传
2)csrf
3)指定上传的文件名称
4) 文件存入服务端
5)图片预览功能
4、富文本框代码
url
# 富文本编辑框 图片上传 re_path(r'^upload/$', views.upload, name='upload'),
views视图
def upload(request): """上传文件""" print(request.FILES) # 获取文件name img = request.FILES.get("upload_img") print(img.name) # 文件存取路径 import os from cnblog import settings img_path = os.path.join(settings.MEDIA_ROOT, "add_article_img", img.name) # 图片读取,写入到服务端 with open(img_path, "wb") as f: for line in img: f.write(line) # 文件预览功能 response = { "error":0, "url":"/media/add_article_img/%s" % img.name } import json return HttpResponse(json.dumps(response))
模板层的富文本编辑框
<div class="content form-group"> <label for="">内容(Kindeditor编辑器,不支持拖放/粘贴上传图片) </label> <div> <textarea id="editor_id" name="content" style="width:700px;height:300px;"></textarea> </div> </div>
JavaScript代码
<script charset="utf-8" src="/static/kindeditor/kindeditor-all-min.js"></script> <script src="/static/js/jquery-3.2.1.min.js"></script> <script> KindEditor.ready(function (K) { window.editor = K.create('#editor_id', { width: "800", height: "600", // 自定制 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' ], // textarea可以拉伸 resizeType: 1, //文件上传的处理视图 uploadJson: "/upload/", //文件上传的参数 extraFileUploadParams: { "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(), }, // 文件上传的name filePostName:"upload_img", }); }); </script>
3、文章摘要的保存
1、只去前150个字符,{{ article.desc|safe }}
2、未闭合的标签
4、bs的简单应用,xss攻击
1、BeautifulSoup
对于HTML/XML数据的筛选,BeautifulSoup也是比较常用且使用简单的技术,
BeautifulSoup是一种非常优雅的专门用于进行HTML/XML数据解析的一种描述语言,可以很好的分析和筛选HTML/XML这样的标记文档中的指定规则数据
在数据筛选过程中其基础技术是通过封装HTML DOM树实现的一种DOM操作,通过加载网页文档对象的形式,从文档对象树模型中获取目标数据
from bs4 import BeautifulSoup s = "<h1>hello</h1> <span>world</sapn> <script>alert(1111)</script>" soup = BeautifulSoup(s, "html.parser") # 按照html格式过滤 print(soup.text) # 过滤掉标签,只剩下text文本 print(soup.find_all()) # 按标签进行截断 for tag in soup.find_all(): print(tag.name) # 打印标签的name if tag.name == "script": tag.decompose() # Recursively destroys the contents of this tree. print(str(soup))
2、bs4模块预防xss攻击
@login_required def add_article(request): if request.method == "POST": title = request.POST.get('title') content = request.POST.get('content') # 过滤 from bs4 import BeautifulSoup soup = BeautifulSoup(content, "html.parser") for tag in soup.find_all(): if tag.name == "script": tag.decompose() # 获取文本,进行截取,赋值给desc desc = soup.text[0:150] models.Article.objects.create(title=title,content=str(soup),desc=desc, user=request.user) return redirect("/cn_backend/") return render(request, "backend/add_article.html", locals())