• Django:模板template(二)


    将跨站请求伪造和验证码的东西记一下

    CSRF

    Cross Site Request Forgery。跨站请求伪造

    链接:GET请求;表单:POST请求

    某些恶意的网站上,包含链接、表单、按钮、JavaScript。利用用户在浏览器上的认证信息试图在网站上完成某些操作,称为CSRF(跨站请求伪造)

    例子:

    设计两个页面,一个用于提交请求(POST),一个用于展示请求提交的数据

    booktest/urls.py

    urlpatterns = [
        url('^csrf1$',views.csrf1, name="csrf1"),
        url('^csrf2$',views.csrf2, name="csrf2"),
    ] 

    booktest/views.py

    def csrf1(request):
        context = {}
        return render(request, 'booktest/csrf1.html', context)
    
    def csrf2(request):
        uname = request.POST['uname']
        context = {'uname': uname}
        return render(request, 'booktest/csrf2.html', context)

    templates/booktest/csrf1.html

    <body>
        <form method="post" action="/booktest/csrf2">
            <input type="text" name="uname"/>
            <input type="submit" value="提交"/>
        </form>
    </body>

    templates/booktest/csrf2.html

    <body>
        {{ uname }}
    </body>

    输入姓名,点击提交按钮,会出现如下效果

     

    出现这个是因为django默认使用了CSRF的认证。把Django中的CSRF功能关闭

    django4/settings.py

    MIDDLEWARE_CLASSES = (
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        #'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'django.middleware.security.SecurityMiddleware',
    )

     

    改成发布模式

    django4/settings.py

    DEBUG = False
    
    ALLOWED_HOSTS = ['*']

    然后,启动服务器。需要带上IP地址

    python manage.py runserver 192.168.30.2:8080

    此时,在浏览器上访问服务器的时候,输入的URLhttp://192.168.30.2:8080/booktest/csrf1 

    注意:现在是真实访问服务器的场景。

    任意提交数据,都可以在csrf2中显示(比如嵌入一段html代码)

    <script>
    for(;;) alert(123);
    </script>

    另外,还有一种可能。现在访问服务器上的URL http://192.168.30.2:8080/booktest/csrf1 获得一个网页的时候,可以把网页的源码抠下来。

    MIDDLEWARE_CLASSES = (
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'django.middleware.security.SecurityMiddleware',
    )

    但是禁止了CSRF结果就会连自己都无法访问了(http://192.168.30.2:8080/booktest/csrf1 )所以不能这样做。

    防止跨域攻击的方法:在csrf1.html中,在表单中添加一个标签

    <body>
        <form method="post" action="/booktest/csrf2">
            {% csrf_token %}
            <input type="text" name="uname"/>
            <input type="submit" value="提交"/>
        </form>
    </body>

    此时,访问http://192.168.30.2:8080/booktest/csrf1 的时候,查看源码,会发现表单中多了一项

    这个就是CSRF的保护措施了

    此时,只有在服务器的URL http://192.168.30.2:8080/booktest/csrf1  http://192.168.30.2:8080/booktest/csrf2 发送请求,才能接收。而在本地的URL file:///D:/gz1833_python/20180918/test.html http://192.168.30.2:8080/booktest/csrf2 发送请求,则会有403的错误(Forbidden CSRF verification failed)。

    验证码

    验证码的作用:防爬虫、减轻服务器的压力、防CSRF

    原理:画一张图。图片上随机输出几个字。要求登录的人输入值要和图片随机生成的值一致

    首先,我们要让服务器返回一张图片,需要安装一个库pillow

    pip install pillow

    安装后在python终端尝试:

    from PIL import Image, ImageDraw, ImageFont
    
    # Image:画布
    # ImageDraw:画笔
    # ImageFont:字体(推荐使用一个字体库FreeFont)
    
    # 注意:访问服务器的图片,响应头中的MIME类型必须为image/png或image/jpeg(之前都是text/html)

    编写返回图片验证码的代码

    booktest/urls.py

    urlpatterns = [
        url('^verifyCode$',views.verifyCode, name="verifyCode"),
    ] 

    booktest/views.py

    def verifyCode(request):
        from PIL import Image, ImageDraw, ImageFont
        import random
        # 规定宽高 宽和高的比例决定验证码的长度是多少 这里是100/25=4
        width = 100
        height = 25
        # 背景色
        bgColor = (63,63,63) # 较深
        # 创建画布
        # 参数1 mode 模式 RGB
        # 参数2 size 长度为2的元组  (width, height)
        # 参数3 color 画布的背景色 长度为3的元组 (R,G,B)
        image = Image.new('RGB', (width, height), bgColor)
        # 创建画笔
        # 参数1 im 画布对象
        # 参数2 mode 模式 默认为None 
        draw = ImageDraw.Draw(image)
        # 创建字体
        # 参数1 font 字体文件
        # 参数2 字体大小
        font = ImageFont.truetype('FreeMono.ttf', 24)
        # 文字
        text = '0123456789'
        textTemp = ''
        # 逐个描绘字符
        for i in range(4):
            textTemp1 = text[random.randrange(0,len(text))]
            textTemp += textTemp1
            # 使用画笔对象在画布上描绘字符
            # 参数1 xy 要描绘的字符左上角的坐标 长度为2的元组
            # 参数2 text 要描述的字符 
            # 参数3 fill 要描述的字符的颜色
            # 参数4 font 字体
            draw.text((i*25,0), textTemp1, (255,255,255), font)
    
        print(textTemp)        
        # 把画布保存到内存中
        #import cStringIO # python2的内存库
        import io # python3中的内存库
        buf = io.BytesIO()
        image.save(buf, 'png')
        # 将内存流中的内容输出到客户端
        return HttpResponse(buf.getvalue(), 'image/png')

    接下来在网页上显示验证码

    booktest/urls.py

    urlpatterns = [
        url('^verifyCode$',views.verifyCode, name="verifyCode"),
        url('^verifyTest$',views.verifyTest, name="verifyTest"),
    ]

    booktest/views.py

    def verifyTest(request):
        context = {}
        return render(request, 'booktest/verifyTest.html', context)

    templates/booktest/verifyTest.html

    <body>
        <form method="post" action="/booktest/verifyTest2">
            {% csrf_token %}
            姓名:<input type="text" name="uname"/><br/>
            验证码:<input type="text" name="verifycode"/><img src="/booktest/verifyCode"><br/>
            <input type="submit" value="提交"/>
        </form>
    </body>

    verifyCode中,把随机产生的验证码保存到session

    booktest/views.py

    def verifyCode(request):
        from PIL import Image, ImageDraw, ImageFont
        ... ...
        print(textTemp)
    
        # 保存到session中
        request.session['code'] = textTemp
        
        # 把画布保存到内存中
        ... ...
        

    添加路由

    booktest/urls.py

    urlpatterns = [
        url('^verifyTest2$',views.verifyTest2, name="verifyTest2"),
    ]  

    booktest/views.py

    def verifyTest2(request):
        ori_code = request.session['code']
        post_code = request.POST['verifycode']
        print('ori_code:%s, post_code:%s' % (ori_code, post_code))
        if ori_code == post_code:
            return HttpResponse('ok')
        else:
            return HttpResponse('fail')

    访问 http://127.0.0.1:8080/booktest/verifyTest 提交正确/错误验证码,后台可以自行检查了。

  • 相关阅读:
    (转)UIMenuController的使用,对UILabel拷贝以及定制菜单
    (转)ios多线程开发——NSOperation详解
    IOS custom statusBar 思路
    objectiveC的@property(atomic, retain)对引用计数的影响
    A Generic Particle IO Library
    RenderMan与CG生产流程简述
    Maya Mesh Relaxation Deformer
    个人黄金市场交易记录/Personal Gold Market Operation Record
    Implementation of TLRW ReadWrite Lock
    给想雇佣我的人说的话/Some words to somebody who want to hire me.
  • 原文地址:https://www.cnblogs.com/kumata/p/9692053.html
Copyright © 2020-2023  润新知