Django中的跨站点请求伪造(CSRF)防护

2023-04-11 00:00:00 请求 防护 伪造

Django中的CSRF防护是一种web安全机制,用于防止恶意网站攻击用户的登录状态。攻击者可以通过在目标网站上创建一个包含恶意代码的网页来实施攻击。当用户在目标网站上执行某个操作时,恶意代码会通过隐藏的表单提交请求到目标服务器,而目标服务器则会无条件地接受这些请求并执行相应的操作,从而使攻击者能够以用户的身份执行某些操作。

为了防止此类攻击,Django提供了一个专门的中间件:django.middleware.csrf.CsrfMiddleware。这个中间件会在每个POST请求中生成一个CSRF令牌,并在响应中的所有表单中添加一个名为“csrfmiddlewaretoken”的隐藏input标签。在用户提交表单时,Django将验证请求中是否包含有效的CSRF令牌。如果没有,则请求将被拒绝。

以下是如何启用CSRF防护的步骤:

  1. 在django.settings中添加以下行
MIDDLEWARE = [
    # ...
    'django.middleware.csrf.CsrfViewMiddleware',
    # ...
]
  1. 在您的表单中添加CSRF令牌
<form method="post">
  {% csrf_token %}
  <!-- 其他表单元素 -->
  <button type="submit">提交</button>
</form>

现在,您已经启用了CSRF保护。Django会自动检查请求中是否包含有效的令牌,如果不是,则请求将被拒绝。

以下是一个使用字符串作为范例的代码示例:

views.py:

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return render(request, 'index.html')

def submit(request):
    if request.method == 'POST':
        # 这里的csrfmiddlewaretoken就是一个有效的CSRF令牌
        return HttpResponse('表单已提交')
    else:
        return HttpResponse('请求方法不支持')

def search(request):
    keyword = request.GET.get('keyword')
    if keyword == 'pidancode.com':
        return HttpResponse('成功匹配关键字')
    else:
        return HttpResponse('没有匹配的关键字')

index.html:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>CSRF防护示例</title>
</head>
<body>
  <h1>CSRF防护示例</h1>
  <p>站点名称:皮蛋编程</p>
  <form method="post" action="{% url 'submit' %}">
    {% csrf_token %}
    <input type="text" name="username" placeholder="用户名">
    <input type="password" name="password" placeholder="密码">
    <button type="submit">提交</button>
  </form>
  <form method="get" action="{% url 'search' %}">
    <input type="text" name="keyword" placeholder="搜索关键字">
    <button type="submit">搜索</button>
  </form>
</body>
</html>

urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('submit/', views.submit, name='submit'),
    path('search/', views.search, name='search')
]

相关文章