前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Django 2.1.7 模板 - CSRF 跨站请求伪造

Django 2.1.7 模板 - CSRF 跨站请求伪造

作者头像
Devops海洋的渔夫
发布2019-07-02 17:59:22
1.9K0
发布2019-07-02 17:59:22
举报
文章被收录于专栏:Devops专栏

相关篇章

Django 2.1.7 创建应用模板

Django 2.1.7 配置公共静态文件、公共模板路径

Django 2.1.7 模板语言 - 变量、标签、过滤器、自定义过滤器、模板注释

Django 2.1.7 模板继承

Django 2.1.7 模板 - HTML转义

参考文献

https://docs.djangoproject.com/zh-hans/2.1/topics/templates/

CSRF

CSRF全拼为Cross Site Request Forgery,译为跨站请求伪造。CSRF指攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。

CSRF示意图如下:

如果想防止CSRF,首先是重要的信息传递都采用POST方式而不是GET方式,接下来就说POST请求的攻击方式以及在Django中的避免。

示例

下面开启两个Django服务,来模拟一下攻击过程。

首先来构建第一个Django项目

1)打开assetinfo/views.py文件,创建视图login,login_check, post和post_action。

代码语言:javascript
复制
def login(reqeust):
    return render(reqeust, '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('发帖失败')

2)打开assetinfo/urls.py文件,配置url。

代码语言:javascript
复制
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),
]

3)在templates/assetinfo/目录下创建login.html和post.html。

login.html

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
</head>
<body>
<form method="post" action="/assetinfo/login_check/">
    用户名:<input type="text" name="username"/><br/>
    密码:<input type="password" name="password"/><br/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

post.html

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>发帖页面</title>
</head>
<body>
<form method="post" action="/assetinfo/post_action/">
    标题:<input type="text" name="title"/><br/>
    内容:<textarea name="content"></textarea>
    <input type="submit" value="发帖"/>
</form>
</body>
</html>

4)启动运行服务器。

代码语言:javascript
复制
python3 manage.py runserver

5)在浏览器中输入如下网址,将这个标签称为网站A。

http://127.0.0.1:8000/assetinfo/login/

浏览效果如下图:

输入账号、密码,登录之后,进入发帖页面,如下:

6)下面使用Django第二个项目来模拟另外一个网站,创建post.html,复制templates/assetinfo/post.html内容,并修改action路径。

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>B网站模拟请求页面</title>
</head>
<body>
<form method="post" action="http://127.0.0.1:8000/assetinfo/post_action/">
    标题:<input type="text" name="title"/><br/>
    内容:<textarea name="content"></textarea>
    <input type="submit" value="发帖"/>
</form>
</body>
</html>

7)在windows中浏览器查看效果如下图,将这个标签称为网站B。

8)Django项目中默认启用了csrf保护,现在先禁用,打开第一个项目中的mysite/settings.py文件,注释掉csrf中间件。

9)点击浏览器的第一个标签即网站A,点击"发帖"按钮后如下图:

10)点击浏览器的第二个标签即网站B,点击“发帖”按钮后如下图:

通过action直接访问网站A的地址,成功执行发帖。

对比上面两个步骤,发现无论从网站A还是网站B都可以访问网站A的post_action视图,这就是不安全的。

防止CSRF

1)Django提供了csrf中间件用于防止CSRF攻击,只需要在网站A的mysite/settings.py中启用csrf中间件即可。

要注意,Django 2 开始开启中间件不是默认生产的MIDDLEWARE_CLASSES中编写,需要写到MIDDLEWARE中,如下:

代码语言:javascript
复制
MIDDLEWARE = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
)

2)回到windows浏览器中,分别在网站A、网站B中点击“提交”按钮,效果一样,如下图:

3)这下麻烦了,因为网站A自己也不能访问了,接下来templates/assetinfo/post.html内容,在form表单中使用标签csrf_token。

代码语言:javascript
复制
{% csrf_token %}

4)回到windows浏览器中,在网站A中点击“提交”按钮,效果如下图:

5)回到windows浏览器中,在网站B中点击“提交”按钮,效果如下图:

好了,Django中成功完成CSRF防护。

总结

  • 重要信息如金额、积分等,采用POST方式传递
  • 启用CSRF中间件,默认启用
  • 在form表单中post提交时加入标签csrf_token

保护原理

加入标签后,可以查看post.html的源代码,发现多了一个隐藏域。

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.06.29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 相关篇章
  • 参考文献
  • CSRF
  • 示例
    • 首先来构建第一个Django项目
    • 防止CSRF
      • 总结
      • 保护原理
      相关产品与服务
      消息队列 TDMQ
      消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档