循序渐进Python3(十三) --4-- django之csrf使用
2017-02-28 13:06
531 查看
用 django 有多久,跟 csrf 这个概念打交道就有久。
每次初始化一个项目时都能看到 django.middleware.csrf.CsrfViewMiddleware 这个中间件
每次在模板里写 form 时都知道要加一个 {% csrf_token %} tag
每次发 ajax POST 请求,都需要加一个 X_CSRFTOKEN 的 header
某个用户已经登录到你的网站上了,那么当这个用户点击这个恶意网站上的那个链接时,就会向你的网站发来一个请求,
你的网站会以为这个请求是用户自己发来的,其实呢,这个请求是那个恶意网站伪造的。
这样就能避免被 CSRF 攻击。
在返回的 HTTP 响应的 cookie 里,django 会为你添加一个 csrftoken 字段,其值为一个自动生成的 token
在所有的 POST 表单时,必须包含一个 csrfmiddlewaretoken 字段 (只需要在模板里加一个 tag, django 就会自动帮你生成,见下面)
在处理 POST 请求之前,django 会验证这个请求的 cookie 里的 csrftoken 字段的值和提交的表单里的 csrfmiddlewaretoken 字段的值是否一样。如果一样,则表明这是一个合法的请求,否则,这个请求可能是来自于别人的 csrf 攻击,返回 403 Forbidden.
在所有 ajax POST 请求里,添加一个 X-CSRFTOKEN header,其值为 cookie 里的 csrftoken 的值
要启用 django.middleware.csrf.CsrfViewMiddleware 这个中间件。
再次,在所有的 POST 表单元素时,需要加上一个 {% csrf_token %} tag。
在渲染模块时,使用 render。render会处理 csrf_token 这个 tag, 从而自动为表单添加一个名为 csrfmiddlewaretoken 的 input。
【注】csrf 装饰器
全局:
中间件 django.middleware.csrf.CsrfViewMiddleware
局部:
@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
代码:
settings.py
urls.py
views.py
csrf.html
每次初始化一个项目时都能看到 django.middleware.csrf.CsrfViewMiddleware 这个中间件
每次在模板里写 form 时都知道要加一个 {% csrf_token %} tag
每次发 ajax POST 请求,都需要加一个 X_CSRFTOKEN 的 header
什么是 CSRF
CSRF, Cross Site Request Forgery, 跨站点伪造请求。举例来讲,某个恶意的网站上有一个指向你的网站的链接,如果某个用户已经登录到你的网站上了,那么当这个用户点击这个恶意网站上的那个链接时,就会向你的网站发来一个请求,
你的网站会以为这个请求是用户自己发来的,其实呢,这个请求是那个恶意网站伪造的。
Django 提供的 CSRF 防护机制
django 第一次响应来自某个客户端的请求时,会在服务器端随机生成一个 token,把这个 token 放在 cookie 里。然后每次 POST 请求都会带上这个 token,这样就能避免被 CSRF 攻击。
在返回的 HTTP 响应的 cookie 里,django 会为你添加一个 csrftoken 字段,其值为一个自动生成的 token
在所有的 POST 表单时,必须包含一个 csrfmiddlewaretoken 字段 (只需要在模板里加一个 tag, django 就会自动帮你生成,见下面)
在处理 POST 请求之前,django 会验证这个请求的 cookie 里的 csrftoken 字段的值和提交的表单里的 csrfmiddlewaretoken 字段的值是否一样。如果一样,则表明这是一个合法的请求,否则,这个请求可能是来自于别人的 csrf 攻击,返回 403 Forbidden.
在所有 ajax POST 请求里,添加一个 X-CSRFTOKEN header,其值为 cookie 里的 csrftoken 的值
Django 里如何使用 CSRF 防护
首先,最基本的原则是:GET 请求不要用有副作用。也就是说任何处理 GET 请求的代码对资源的访问都一定要是“只读“的。要启用 django.middleware.csrf.CsrfViewMiddleware 这个中间件。
再次,在所有的 POST 表单元素时,需要加上一个 {% csrf_token %} tag。
在渲染模块时,使用 render。render会处理 csrf_token 这个 tag, 从而自动为表单添加一个名为 csrfmiddlewaretoken 的 input。
【注】csrf 装饰器
全局:
中间件 django.middleware.csrf.CsrfViewMiddleware
局部:
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
代码:
settings.py
""" Django settings for my19django project. Generated by 'django-admin startproject' using Django 1.10.3. For more information on this file, see https://docs.djangoproject.com/en/1.10/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.10/ref/settings/ """ import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '=_!qf8#b(*b-bd0texdrf9og219b1guo=uepdsll6v(6(n#4*w' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'my19django.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'my19django.wsgi.application' # Database # https://docs.djangoproject.com/en/1.10/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # Password validation # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/1.10/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.10/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), )
urls.py
from django.conf.urls import url from django.contrib import admin from myapp01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.login), url(r'^csrf/', views.csrf), ]
views.py
from django.shortcuts import render def csrf(req): return render(req, 'csrf.html')
csrf.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/csrf/" method="post"> {% csrf_token %} <input type="text" name="v"/> <input type="submit" name="提交"/> </form> <input type="button" value="Ajax提交" onclick="DoAjax();"/> <script src="/static/jquery-2.1.4.min.js"></script> <script src="/static/jquery.cookie.js"></script> <script> // 去cookie中获取值 var csrftoken = $.cookie('csrftoken'); function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } }); function DoAjax(){ $.ajax({ url: '/csrf/', type: 'POST', data: {'k1': 'v1'}, success: function (data) { console.log(data); } }) } </script> </body> </html>
相关文章推荐
- 循序渐进Python3(十三) --5-- django请求处理流程
- 循序渐进Python3(十三) --3-- django之form表单(为自动生成的html标签添加样式)
- 循序渐进Python3(十三) --7-- django之models
- 循序渐进Python3(十三) --2-- django之form表单(自动生成html标签和自定制提示信息)
- 循序渐进Python3(十三) --0-- django之form表单
- Python-django中ajax使用POST时使用csrf_token
- 循序渐进Python3(十三) --1-- django之form表单
- 循序渐进Python3(十三) --8-- django之admin
- python 使用django post提交时出现 CSRF verification failed. Request aborted.
- 使用Python的Django框架结合jQuery实现AJAX购物车页面
- 使用 Django 和 Python 开发 Web 站点
- Python的Django框架中if标签的相关使用
- 解决Django和EasyUI搭配使用时出现的CSRF问题
- python django中使用sqlite3数据库 存储二进制数据ByteArray
- python virtualenv django 使用
- Ubuntu Python2.7 django1.3 安装使用过程部分笔记
- Python系列视频教程: Django【13讲】第13讲 表单使用
- 在SAE(新浪云平台)上使用 python django库编写网站
- Python爬虫(十三)_案例:使用XPath的爬虫
- python——使用django打造个人博客(1)