导读:很多朋友问到关于djangocsrf怎么认证的的相关问题,本文首席CTO笔记就来为大家做个详细解答,供大家参考,希望对大家有所帮助!一起来看看吧!
页面刷新时怎么进行csrf token 判断
我上次在用django的时候遇到过这个问题,资料如下:django对POST请求需要csrf_token验证,后端会检测前端发过来的token,如果有问题可以会出现403Forbidden的错误。这个token是由后端在页面GET请求页面文件的时候就放进去的,可以在模板中使用
如何验证csrf 漏洞
CSRF(Cross Site Request Forgey)是排在OWASP Top10第5位的漏洞,它迫使已被认证的用户在Web系统上执行其所不欲的操作。这种攻击依赖于以下:
1) Web浏览器对会话相关信息的处理方式(如cookie或Http认证信息)
2) 攻击者对正确的Web系统的URL的了解;
3) 应用会话管理仅依赖于浏览器所了解的信息;
4) 一些HTML的tag会导致对http(s)资源的直接访问其中,前3点是确认系统是否存在该漏洞的主要前提,第4点则是用来帮助攻击者利用该漏洞的。
第1点:浏览器自动发送用于识别用户会话的信息,假设site是一个Web应用站点,victim是一个已经在该系统上经过认证的用户。在server的响应中,site发送一个带有代表victim身份的cookie给victim,原则上,一旦浏览器接收到了服务器发送的cookie,就会在后面对站点的访问中都带上这个cookie;
第2点:如果应用在URL中没有使用会话相关的信息,那就意味着应用的URL,它们的参数,相应的值可以被识别。
第3点:是指诸如cookie、或者是基于http的认证信息,存放在浏览器中后,就会包含在后面的每次请求中。
下面,我们用Get方法在做个例子,如果用户已经通过了认证,那么在他做下一次请求时,请求数据中会自动加上cookie
GET请求一般会有多种原因产生,
* 用户真正在访问Web系统;
* 用户在访问地址栏中切实敲入了URL;
* 用户点击了一个连接指向了这个URL;
这些调用对于系统来说是无法区别的,特别的,第三种方式相对来说是极为危险的,有很多种方法可以用来仿造连接的真实属性,连接可以被嵌入到一封邮件中,或者在某个恶意网站上,看上去这个连接好像是在访问另一个网站,而事实上却是被引到了Web系统的访问上。如果用户点击了连接,由于它已经被系统认证通过了,浏览器就会对系统提交一个待用认证信息的GET请求。这就在系统上完成了一个操作(尽管这个操作不是用户本身所期望做的)。
当我用django的超级用户登录时候,出现CSRF的错误,如图,怎么解决啊??
需要在form后面加上csrf_token。如:
form method="post"{% csrf_token %}
xxx
/form
或者修改django源码:django/middleware/csrf.py process_view
在“# If the user doesn't have a CSRF cookie”上面增加以下代码:
if request.path.startswith('/admin'):
return accept()
如果django版本为1.2.5,则修改为:
if request.path.startswith('/admin'):
return self._accept(request)
这表示 请求url是/admin的话,即使form后面没带csrf_token也可以访问。
csrf_token的了解
django中写form表单时csrf_token的作用:
Django下的CSRF预防机制
CSRF预防机制
CSRF的防御可以从服务端和客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的CSRF防御也都在服务端进行。
token防御的整体思路是:
第一步:后端随机产生一个token,把这个token保存在SESSION状态中;同时,后端把这个token交给前端页面;
第二步:下次前端需要发起请求(比如发帖)的时候把这个token加入到请求数据或者头信息中,一起传给后端;
第三步:后端校验前端请求带过来的token和SESSION里的token是否一致;
1、Django下的CSRF预防机制
django 第一次响应来自某个客户端的请求时,会在服务器端随机生成一个 token,把这个 token 放在 cookie 里。然后每次 POST 请求都会带上这个 token,
这样就能避免被 CSRF 攻击。
在 templete 中, 为每个 POST form 增加一个 {% csrf_token %} tag. 如下:
在返回的 HTTP 响应的 cookie 里,django 会为你添加一个 csrftoken 字段,其值为一个自动生成的 token
在所有的 POST 表单模板中,加一个{% csrf_token %} 标签,它的功能其实是给form增加一个隐藏的input标签,如下
,而这个csrf_token = cookie.csrftoken,在渲染模板时context中有context['csrf_token'] = request.COOKIES['csrftoken']
在通过表单发送POST到服务器时,表单中包含了上面隐藏了crsrmiddlewaretoken这个input项,服务端收到后,django 会验证这个请求的 cookie 里的 csrftoken 字段的值和提交的表单里的 csrfmiddlewaretoken 字段的值是否一样。如果一样,则表明这是一个合法的请求,否则,这个请求可能是来自于别人的 csrf 攻击,返回 403 Forbidden.
在通过 ajax 发送POST请求到服务器时,要求增加一个x-csrftoken header,其值为 cookie 里的 csrftoken 的值,服务湍收到后,django会验证这个请求的cookie里的csrftoken字段与ajax post消息头中的x-csrftoken header是否相同,如果相同,则表明是一个合法的请求
具体实现方法
django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。
全局:
中间件 django.middleware.csrf.CsrfViewMiddleware
局部:
@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
注:from django.views.decorators.csrf import csrf_exempt,csrf_protect
1、原理
在客户端页面上添加csrftoken, 服务器端进行验证,服务器端验证的工作通过'django.middleware.csrf.CsrfViewMiddleware'这个中间层来完成。在django当中防御csrf攻击的方式有两种:
1.在表单当中附加csrftoken
2.通过request请求中添加X-CSRFToken请求头。
注意:Django默认对所有的POST请求都进行csrftoken验证,若验证失败则403错误侍候。
Django 设置 cookie 中的 csrftoken
VUE向django发送post返回403:CSRF Failed: CSRF token missing or incorrect解决方案:
如何利用Django-auth做用户认证
首先,让我们开始创建项目和APP,前面我也很详细的说明了如何创建项目和APP。
创建数据库,和相关用户的权限。
root@CD-FTP-VPN:/opt/jastme# tree
.
|-- jastme
| |-- __init__.py
| |-- __init__.pyc
| |-- settings.py
| |-- settings.pyc
| |-- urls.py
| |-- urls.pyc
| |-- wsgi.py
| `-- wsgi.pyc
|-- login
| |-- admin.py
| |-- __init__.py
| |-- __init__.pyc
| |-- models.py
| |-- models.pyc
| |-- tests.py
| |-- views.py
| `-- views.pyc
|-- manage.py
`-- start.sh
2 directories, 18 files
root@CD-FTP-VPN:/opt/jastme#
使用python manage.py syncdb 来创建一个叫jastme,密码为jastme的超级用户。我们可以用Django-admin来管理这些用户。
首先看看setting.py
root@CD-FTP-VPN:/opt/jastme# more jastme/settings.py
"""
Django settings for jastme project.
For more information on this file, see
For the full list of settings and their values, see
"""
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# Quick-start development settings - unsuitable for production
# See
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'r!1=i^3qhwglr(zf*9n*ii!b_oy2h()ics(6(de3wuo0-oh8h'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
TEMPLATE_DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = (
# 'django.contrib.admin', #注释掉admin
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'login',
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware', #这个中间件是防止跨站攻击的。有意思的朋友可以去搜索下。
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
ROOT_URLCONF = 'jastme.urls'
WSGI_APPLICATION = 'jastme.wsgi.application'
# Database
#
DATABASES = { #数据库的相关配置
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'jastme',
'USER':'jastme',
'PASSWORD':'jastme',
'HOST':'localhost',
'PORT':'3306',
}
}
# Internationalization
#
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
#
STATIC_URL = '/static/'
TEMPLATE_DIRS =( #模板的路径
'/var/www/jastme/',
)
views.py
root@CD-FTP-VPN:/opt/jastme# more login/views.py
from django.shortcuts import render
from django.contrib import auth
# Create your views here.
from django.shortcuts import render_to_response
from django.contrib.auth import authenticate, login
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse,HttpResponseRedirect
from django.contrib.auth.decorators import login_required
def my_login(request): #我们自定义一个函数,这个函数名字一定不要写成login,因为Django有有login模块。
if request.method == 'POST': #我们使用POST的方法来获取从HTML传递过来的表单内容
username = request.POST@['username'] #获取账号和密码
password = request.POST@['password']
user = authenticate(username=username, password=password) #我们用user来实例化 authenticate(username=username, password=password)
if user is not None: #用户名不为空
if user.is_active: #为激活用户
login(request, user) #调用django.contrib.auth中的login函数,可以具体去看看源码
return HttpResponseRedirect('/main') #登陆成功就重定向到主页
else:
login_error = 'login error.'
return render_to_response('login.html', {'login_error' : login_error, 'is_display' : 'display:block'}) #失败则返回登陆页面
return render_to_response('login.html', {'is_display' : 'display:none'}) #同理
@login_required #调用了这个修饰器,就可以让这个页面在成功登陆后才能访问
def main(request):
return HttpResponse('login sucess') #直接返回这个字符串
再看看urls.py
root@CD-FTP-VPN:/opt/jastme# more jastme/urls.py
from django.conf.urls import patterns, include, url
#from django.contrib import admin
from login.views import my_login,main #这里是我们导入的项目中的views.py中的模块,就是我们自己写的函数
#from django.contrib.auth.views import login, logout
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'jastme.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
# url(r'^admin/', include(admin.site.urls)),
(r'^main/$',main),
(r'^login/$',my_login),
)
login.html
root@CD-FTP-VPN:/var/www/jastme# pwd
/var/www/jastme
root@CD-FTP-VPN:/var/www/jastme# ls
login.html
form action="" method="POST" #在此页面以POST的方式来提交参数
input type=text name="username"
input type=text name="password"
input type=submit value="send"
/form
结语:以上就是首席CTO笔记为大家整理的关于djangocsrf怎么认证的的相关内容解答汇总了,希望对您有所帮助!如果解决了您的问题欢迎分享给更多关注此问题的朋友喔~