Web框架之Django【笔记】- ModelForm Ajax全套 文件上传 验证码 KindEditor Xss攻击 单例模式 事务操作 其他

笔记1:ModelForm Ajax全套 文件上传 验证码 KindEditor

内容回顾:
	
	Model
		- 数据库操作
		- 验证
		class A(MOdel):
			user = 
			email = 
			pwd = 
		
	Form
		- class LoginForm(Form): 
			email = fields.EmailField()
			user = 
			pwd = 
			
		- is_valid -> 每一个字段进行正则(字段内置正则)+clean_字段 -> clean(__all__)  -> _post_clean
		- cleand_data
		- error
	--------> 推荐 <---------
		
一、ModelForm
	参考博客:
		http://www.cnblogs.com/wupeiqi/articles/6229414.html
	
	Model + Form => 验证 + 数据库操作
	- class LoginModelForm(xxxxx): 
		 利用model.A中的字段
		 
	1. 生成HTML标签:class Meta: ...
	2. 生成默认值(编辑):mf = xxxModelForm(instance=ModelObj)
	3. 额外的标签(免登录单选框), is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput())
	4. 各种验证 is_valid() -> 各种钩子clean...
	5. 	mf.save()
		# 查看源码分析:
		# 或
		instance = mf.save(False)
		instance.save()
		mf.save_m2m()
	6.model与form紧耦合,适用于小程序,大程序不要用它。

二、Ajax
	参考博客:
		http://www.cnblogs.com/wupeiqi/articles/5703697.html
	
	原生
		
	jQuery
	
	伪Ajax操作
	
	时机:
		如果发送的是【普通数据】 -> jQuery,XMLHttpRequest,iframe
	
三、文件上传(预览)
	
	- Form提交
	- Ajax上传文件
	
	时机:
		如果发送的是【文件】 -> iframe,jQuery(FormData),XMLHttpRequest(FormData),
	
	
四、图片验证码 + Session
	
	- session
	- check_code.py(依赖:Pillow模块和字体文件)
	- src属性后面加?



五、CKEditor,UEEditor,TinyEditor,KindEditor(***)
	参考博客:
		http://www.cnblogs.com/wupeiqi/articles/6307554.html
		
	- 基本使用
	- 文件上传,多文件上传,文件空间管理
	- XSS攻击(过滤的函数或类) 下节课说...
	
作业:

	主站:
		http://127.0.0.1:8000/   				博客首页
		http://127.0.0.1:8000/zhaofan/1.html	某人的某篇博客
	个人博客:
		http://127.0.0.1:8000/zhaofan.html					某人的博客
		http://127.0.0.1:8000/zhaofan/tag/python.html		某人的博客筛选
		http://127.0.0.1:8000/zhaofan/catetory/mvc.html		某人的博客筛选
		http://127.0.0.1:8000/zhaofan/date/2011-11.html		某人的博客筛选
	个人后台管理:
		http://127.0.0.1:8000/backend/base-info.html
		http://127.0.0.1:8000/backend/tag.html
		http://127.0.0.1:8000/backend/category.html
		http://127.0.0.1:8000/backend/article.html
		http://127.0.0.1:8000/backend/add-article.html

验证码

urls:

# 需要的文件:
# (1)check_code.py  (2) Monaco.ttf字体文件 (3)Html文件
url('^checkcode$', views.checkcode),     # 用户访问的url页面(验证码单独新url)
url('^radom_code', views.radom_code),    # 前端POST提交验证码的url

views:

###################################验证码示例###############################
from io import BytesIO  # 从内存中读取
from utils.check_code import create_validate_code
def checkcode(request):
    """
        验证码
        :param request:
        :return:
    """
    # data = open('static/imgs/avatar/20130809170025.png','rb').read()
    # return HttpResponse(data)

    # 文件的读取方法 - 重在理解思路
    # 1. 创建一张图片 pip3 install Pillow
    # 2. 在图片中写入随机字符串
    # obj = object()
    # 3. 将图片写入到制定文件
    # 4. 打开制定目录文件,读取内容
    # 5. HttpResponse(data)
    '''
    img, code = create_validate_code()
    # img.save('文件句柄', '文件格式')
    # 写入文件
    f = open('utils/uson_checkcode.png', 'wb')
    img.save(f, 'PNG')
    f.close()
    # return render(request, 'radom_code.html')
    # 读取文件
    return HttpResponse(open('utils/uson_checkcode.png', 'rb').read())
    '''

    # 内存的存储方法
    stream = BytesIO()  # 从内存读取
    img, code = create_validate_code()  # 用户访问页面,创建并生成图片对象和字符串给用户

    img.save(stream, 'PNG')  # 将以png为后缀的图片对象存放到内存中
    request.session['CheckCode'] = code  # 并保存到session中,用于post提交验证用户输入是否一致

    return HttpResponse(stream.getvalue())  # 从内存中获取图片返回给用户

def radom_code(request):
    if  request.method == 'POST':
        code = request.POST.get('check_code') # 用户输入input的name:check_code
        if code.upper() == request.session['CheckCode'].upper():
            print('验证码正确')
        else:
            print('验证码错误')
    return render(request, 'day24-app06/radom_code.html')

html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .checkcode{
            width: 130px;
            height: 33px;
            border: 1px solid red;
        }
    </style>
</head>
<body>
    <div class="checkcode">
        <img src="/cohui/checkcode" onclick="changeCheckCode(this);">
    </div>
    <script>
        function changeCheckCode(ths) {
            // ths.src = "/cohui/checkcode" + '?';  // 只能改变一次
            ths.src = ths.src + '?';  // 只有url动态改变,验证码的url才能不断被提交
        }
    </script>
</body>
</html>

check_code.py:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import random

# pip3 install Pillow
from PIL import Image, ImageDraw, ImageFont, ImageFilter

_letter_cases = "abcdefghjkmnpqrstuvwxy"  # 小写字母,去除可能干扰的i,l,o,z
_upper_cases = _letter_cases.upper()  # 大写字母
_numbers = ''.join(map(str, range(3, 10)))  # 数字
init_chars = ''.join((_letter_cases, _upper_cases, _numbers))


def create_validate_code(size=(120, 30),
                         chars=init_chars,
                         img_type="GIF",
                         mode="RGB",
                         bg_color=(255, 255, 255),
                         fg_color=(0, 0, 255),
                         font_size=18,

                         font_type="utils/Monaco.ttf",   # 依赖字体
                         # font_type="Monaco.ttf",

                         length=4,
                         draw_lines=True,
                         n_line=(1, 2),
                         draw_points=True,
                         point_chance=2):
    """
    @todo: 生成验证码图片
    @param size: 图片的大小,格式(宽,高),默认为(120, 30)
    @param chars: 允许的字符集合,格式字符串
    @param img_type: 图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG
    @param mode: 图片模式,默认为RGB
    @param bg_color: 背景颜色,默认为白色
    @param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF
    @param font_size: 验证码字体大小
    @param font_type: 验证码字体,默认为 ae_AlArabiya.ttf
    @param length: 验证码字符个数
    @param draw_lines: 是否划干扰线
    @param n_lines: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效
    @param draw_points: 是否画干扰点
    @param point_chance: 干扰点出现的概率,大小范围[0, 100]
    @return: [0]: PIL Image实例
    @return: [1]: 验证码图片中的字符串
    """

    width, height = size  # 宽高
    # 创建图形
    img = Image.new(mode, size, bg_color)
    draw = ImageDraw.Draw(img)  # 创建画笔

    def get_chars():
        """生成给定长度的字符串,返回列表格式"""
        return random.sample(chars, length)

    def create_lines():
        """绘制干扰线"""
        line_num = random.randint(*n_line)  # 干扰线条数

        for i in range(line_num):
            # 起始点
            begin = (random.randint(0, size[0]), random.randint(0, size[1]))
            # 结束点
            end = (random.randint(0, size[0]), random.randint(0, size[1]))
            draw.line([begin, end], fill=(0, 0, 0))

    def create_points():
        """绘制干扰点"""
        chance = min(100, max(0, int(point_chance)))  # 大小限制在[0, 100]

        for w in range(width):
            for h in range(height):
                tmp = random.randint(0, 100)
                if tmp > 100 - chance:
                    draw.point((w, h), fill=(0, 0, 0))

    def create_strs():
        """绘制验证码字符"""
        c_chars = get_chars()
        strs = ' %s ' % ' '.join(c_chars)  # 每个字符前后以空格隔开

        font = ImageFont.truetype(font_type, font_size)
        font_width, font_height = font.getsize(strs)

        draw.text(((width - font_width) / 3, (height - font_height) / 3),
                  strs, font=font, fill=fg_color)

        return ''.join(c_chars)

    if draw_lines:
        create_lines()
    if draw_points:
        create_points()
    strs = create_strs()

    # 图形扭曲参数
    params = [1 - float(random.randint(1, 2)) / 100,
              0,
              0,
              0,
              1 - float(random.randint(1, 10)) / 100,
              float(random.randint(1, 2)) / 500,
              0.001,
              float(random.randint(1, 2)) / 500
              ]
    img = img.transform(size, Image.PERSPECTIVE, params)  # 创建扭曲

    img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)  # 滤镜,边界加强(阈值更大)

    return img, strs        # img: 图片对象, strs: 验证码字符串

验证码文件点击获取

依赖字体文件点击获取

笔记2:Xss攻击 单例模式 事务操作

XSS过滤特殊标签

处理依赖: 1 pip3 install beautifulsoup4 

XSS示例:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from bs4 import BeautifulSoup


class XSSFilter(object):
    __instance = None

    def __init__(self):
        # XSS白名单
        self.valid_tags = {
            "font": ['color', 'size', 'face', 'style'],
            'b': [],
            'div': [],
            "span": [],
            "table": [
                'border', 'cellspacing', 'cellpadding'
            ],
            'th': [
                'colspan', 'rowspan'
            ],
            'td': [
                'colspan', 'rowspan'
            ],
            "a": ['href', 'target', 'name'],
            "img": ['src', 'alt', 'title'],
            'p': [
                'align'
            ],
            "pre": ['class'],
            "hr": ['class'],
            'strong': []
        }

    @classmethod
    def instance(cls):
        if not cls.__instance:
            obj = cls()
            cls.__instance = obj
        return cls.__instance

    def process(self, content):
        soup = BeautifulSoup(content, 'lxml')
        # 遍历所有HTML标签
        for tag in soup.find_all(recursive=True):
            # 判断标签名是否在白名单中
            if tag.name not in self.valid_tags:
                tag.hidden = True
                if tag.name not in ['html', 'body']:
                    tag.hidden = True
                    tag.clear()
                continue
            # 当前标签的所有属性白名单
            attr_rules = self.valid_tags[tag.name]
            keys = list(tag.attrs.keys())
            for key in keys:
                if key not in attr_rules:
                    del tag[key]

        return soup.renderContents()


if __name__ == '__main__':
    html = """<p class="title">
                        <b>The Dormouse's story</b>
                    </p>
                    <p class="story">
                        <div name='root'>
                            Once upon a time there were three little sisters; and their names were
                            <a href="http://example.com/elsie" class="sister c1" style='color:red;background-color:green;' 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">Tilffffffffffffflie</a>;
                            and they lived at the bottom of a well.
                            <script>alert(123)</script>
                        </div>
                    </p>
                    <p class="story">...</p>"""

    v = XSSFilter.instance().process(html)
    print(v)

基于__new__实现单例模式示例

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from bs4 import BeautifulSoup


class XSSFilter(object):
    __instance = None

    def __init__(self):
        # XSS白名单
        self.valid_tags = {
            "font": ['color', 'size', 'face', 'style'],
            'b': [],
            'div': [],
            "span": [],
            "table": [
                'border', 'cellspacing', 'cellpadding'
            ],
            'th': [
                'colspan', 'rowspan'
            ],
            'td': [
                'colspan', 'rowspan'
            ],
            "a": ['href', 'target', 'name'],
            "img": ['src', 'alt', 'title'],
            'p': [
                'align'
            ],
            "pre": ['class'],
            "hr": ['class'],
            'strong': []
        }

    def __new__(cls, *args, **kwargs):
        """
        单例模式
        :param cls:
        :param args:
        :param kwargs:
        :return:
        """
        if not cls.__instance:
            obj = object.__new__(cls, *args, **kwargs)
            cls.__instance = obj
        return cls.__instance

    def process(self, content):
        soup = BeautifulSoup(content, 'lxml')
        # 遍历所有HTML标签
        for tag in soup.find_all(recursive=True):
            # 判断标签名是否在白名单中
            if tag.name not in self.valid_tags:
                tag.hidden = True
                if tag.name not in ['html', 'body']:
                    tag.hidden = True
                    tag.clear()
                continue
            # 当前标签的所有属性白名单
            attr_rules = self.valid_tags[tag.name]
            keys = list(tag.attrs.keys())
            for key in keys:
                if key not in attr_rules:
                    del tag[key]

        return soup.renderContents()


if __name__ == '__main__':
    html = """<p class="title">
                        <b>The Dormouse's story</b>
                    </p>
                    <p class="story">
                        <div name='root'>
                            Once upon a time there were three little sisters; and their names were
                            <a href="http://example.com/elsie" class="sister c1" style='color:red;background-color:green;' 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">Tilffffffffffffflie</a>;
                            and they lived at the bottom of a well.
                            <script>alert(123)</script>
                        </div>
                    </p>
                    <p class="story">...</p>"""

    obj = XSSFilter()
    v = obj.process(html)
    print(v)

猜你喜欢

转载自www.cnblogs.com/uson/p/11606518.html
今日推荐