了解如何在django 2.1.7中处理csrf跨站请求伪造问题是至关重要的。本文将详细介绍django 2.1.7中关于csrf的相关内容,包括如何设置和使用csrf保护。

相关篇章包括:
- Django 2.1.7 创建应用模板
- Django 2.1.7 配置公共静态文件、公共模板路径
- Django 2.1.7 模板语言 - 变量、标签、过滤器、自定义过滤器、模板注释
- Django 2.1.7 模板继承
- Django 2.1.7 模板 - HTML转义
参考文献:https://www.php.cn/link/1844bd1b6d59ab61b41e110f72b4ef61
CSRF,即Cross Site Request Forgery(跨站请求伪造),是一种攻击者利用你的身份,以你的名义发送恶意请求的攻击方式。CSRF攻击可以导致的危害包括:以你的名义发送邮件、发消息、盗取你的账号,甚至购买商品和进行虚拟货币转账,进而可能导致个人隐私泄露和财产安全问题。
CSRF攻击示意图如下:

为了防止CSRF攻击,首先应确保重要信息的传递使用POST方式而非GET方式。接下来,我们将通过在Django中模拟攻击过程来展示如何避免这种攻击。
示例:模拟CSRF攻击过程
我们将启动两个Django服务来模拟攻击过程。
-
构建第一个Django项目:
打开
assetinfo/views.py文件,创建视图login、login_check、post和post_action。def login(request): return render(request, 'assetinfo/login.html')def login_check(request): username = request.POST.get('username') # 获取用户名 password = request.POST.get('password') # 获取密码
校验
if username == 'smart' and password == '123': request.session['username'] = username # 记住登录用户名 request.session['islogin'] = True # 判断用户是否已登录 return redirect('/assetinfo/post/') else: return redirect('/assetinfo/login/')def post(request): return render(request, 'assetinfo/post.html')
def post_action(request): if request.session['islogin']: username = request.session['username'] return HttpResponse('用户'+username+'发了一篇帖子') else: return HttpResponse('发帖失败')
-
配置URL:
打开
assetinfo/urls.py文件,配置URL。urlpatterns = [
ex:/assetinfo/login
path('login/', views.login), # ex:/assetinfo/login_check path('login_check/', views.login_check), # ex:/assetinfo/post path('post/', views.post), # ex:/assetinfo/post_action path('post_action/', views.post_action),]
-
创建模板文件:
在
templates/assetinfo/目录下创建login.html和post.html。login.html:用户登录 用户名:
密码:post.html:发帖页面 标题:
内容: -
启动服务器:
python3 manage.py runserver
-
访问网站A:
在浏览器中输入
https://www.php.cn/link/d3e2fe4ac9568e0b59ad61ccbc933906,登录后进入发帖页面。

-
模拟网站B:
使用Django的第二个项目创建
post.html,并修改action路径。B网站模拟请求页面 标题:
内容:
-
禁用CSRF保护:
打开第一个项目的
mysite/settings.py文件,注释掉CSRF中间件。
-
测试攻击效果:
在网站A中点击“发帖”按钮:

在网站B中点击“发帖”按钮:


通过
action直接访问网站A的地址,成功执行发帖。发现无论从网站A还是网站B都可以访问网站A的
post_action视图,这是不安全的。
防止CSRF攻击
-
启用CSRF中间件:
在网站A的
mysite/settings.py中启用CSRF中间件。
注意,Django 2开始,中间件配置应在
MIDDLEWARE中:MIDDLEWARE = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', )
-
测试启用CSRF中间件后的效果:
在网站A和网站B中点击“提交”按钮:

-
在表单中添加CSRF令牌:
在
templates/assetinfo/post.html中,添加csrf_token标签:{% csrf_token %}
-
测试网站A的效果:
在网站A中点击“提交”按钮:


-
测试网站B的效果:
在网站B中点击“提交”按钮:

至此,成功在Django中完成CSRF防护。
总结
- 重要信息如金额、积分等,应采用POST方式传递。
- 启用CSRF中间件,默认情况下Django已启用。
- 在表单中POST提交时加入
csrf_token标签进行保护。
保护原理:
加入csrf_token标签后,查看post.html的源代码,会发现多了一个隐藏域:

在浏览器的“开发者工具”中查看Cookie信息:

启用中间件并加入csrf_token标签后,Django会向客户端浏览器写入一条Cookie信息,该信息的值与隐藏域的value属性一致。提交到服务器后,CSRF中间件会先进行验证,如果对比失败则返回403页面,而不会进行后续处理。










