CSRF
-
概念介绍:
CSRF: Cross Site Request Forgery,跨站请求伪造,指攻击者盗用你的身份,以你的名义发送恶意请求,包括:以你的名义发送邮件、发消息、盗取你的账号、购买商品等。 -
造成环境:
- 登录正常网站之后,你的浏览器保存的sessionid,你没有退出。
- 你不小心访问了另外一个网站,并且点击了页面上的按钮。
-
django如何解决:
- django默认提供csrf中间件用于防止csrf攻击,默认开启的,如下图
- 在自己 post 提交表单的时候,加上标签 csrf_token ,如下
<body> <form method="post" action="/post_action/"> {% csrf_token %} <!-- 就是这个 --> 标题:<input type="text" name="title"/><br/> 内容:<textarea name="content"></textarea> <input type="submit" value="发帖"/> </form>
- 在 ajax 请求中和 form 中不一样,ajax如下所示
$.ajaxSetup({ data: {csrfmiddlewaretoken: '{{ csrf_token }}' }, }); // 2. 发送ajax请求 /login_ajax_check $.ajax({ ... })
-
csrf_token 标签工作原理:
- 服务器中加上该标签以后,会发现 html 源码会多一个影藏的 input 标签,标签有个 value值
- 同时服务器会想浏览器发送一个 cookie 信息,键就是 csrftoken 值就是 上面标签的 value 值,在浏览器向服务器请求时,会进行 csrf 检验,失败就会返回 403 页面。
验证码问题
- 验证码的出现就是为了防止暴力请求。
- 流程如下
- 其中一个验证码如下所示(code):
# 安装 PIL 模块 from PIL import Image, ImageDraw, ImageFont from django.utils.six import BytesIO # 改了 from io import BytesIO def verify_code(request): # 引入随机函数模块 import random # 定义变量,用于画面的背景色、宽、高 bgcolor = (random.randrange(20, 100), random.randrange( 20, 100), 255) width = 100 height = 25 # 创建画面对象 im = Image.new('RGB', (width, height), bgcolor) # 创建画笔对象 draw = ImageDraw.Draw(im) # 调用画笔的point()函数绘制噪点 for i in range(0, 100): xy = (random.randrange(0, width), random.randrange(0, height)) fill = (random.randrange(0, 255), 255, random.randrange(0, 255)) draw.point(xy, fill=fill) # 定义验证码的备选值 str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0' # 随机选取4个值作为验证码 rand_str = '' for i in range(0, 4): rand_str += str1[random.randrange(0, len(str1))] # 构造字体对象,ubuntu的字体路径为“/usr/share/fonts/truetype/freefont” font = ImageFont.truetype('FreeMono.ttf', 23) # 构造字体颜色 fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255)) # 绘制4个字 draw.text((5, 2), rand_str[0], font=font, fill=fontcolor) draw.text((25, 2), rand_str[1], font=font, fill=fontcolor) draw.text((50, 2), rand_str[2], font=font, fill=fontcolor) draw.text((75, 2), rand_str[3], font=font, fill=fontcolor) # 释放画笔 del draw # 存入session,用于做进一步验证 request.session['verifycode'] = rand_str #内存文件操作 buf = BytesIO() # 将图片保存在内存中,文件类型为png im.save(buf, 'png') # 将内存中的图片数据返回给客户端,MIME类型为图片png return HttpResponse(buf.getvalue(), 'image/png')
- html 中如下:
<form method="post" action="/verify_yz/"> {%csrf_token%} <input type="text" name="yzm"> <!--如下所示,注意src是直接url地址的 所以肯定需要 url配置和view中对应视图函数--> <img id="yzm" src="/verify_code/"/> <span id="change">看不清,换一个</span> <br> <input type="submit" value="提交"> </form>
- 一般登录,是先验证 验证码 在正确前提下才进行用户名和密码的验证
- 其中一个验证码如下所示(code):
反向解析
- 问题描述:一般网页有很多会导向首页 index 但是 如果首页的 index 改成 index2 那相应的都需要修改,比较麻烦。
- 解决方案:
- 在test4/urls.py(总体urls.py)中为include增加namespace属性
url(r'^',include('booktest.urls',namespace='booktest')),
- 在booktest/urls.py(应用urls.py)为index增加name属性(应用地方) 地方
url(r'^index/$', views.index, name='index'),
- 模板中修改如下:
<a href="{%url 'booktest:index'%}">嘟嘟</a>
- 视图中修改如下:
from django.core.urlresolvers import reverse ... return redirect(reverse('booktest:index'))
- 如果有位置参数:
- booktest/urls.py中如下:
url(r'^fan(\d+)_(\d+)/$', views.index,name='index'),
- 模板中如下:
<a href="{%url 'booktest:index' 2 3 %}">嘟嘟</a>
- 视图中如下:
return redirect(reverse('booktest:fan2', args=(2,3)))
- booktest/urls.py中如下:
- 如果有关键字参数:
- booktest/urls.py中如下:
url(r'^fan(?p<a>\d+)_(?p<b>\d+)/$', views.index,name='index'),
- 模板中如下:
<a href="{%url 'booktest:index' a=2 b=3 %}">嘟嘟</a>
- 视图中如下:
return redirect(reverse('booktest:fan2', kwargs={'a': 2, 'b': 3}))
- booktest/urls.py中如下:
- 在test4/urls.py(总体urls.py)中为include增加namespace属性