django rest framework csrf 令牌丢失或不正确
django rest framework csrf token missing or incorrect
你好,我正在使用 django rest-auth,我在 /password/change/ 中遇到了这个问题,它总是 return csrf 令牌丢失或不正确的问题:
我正在向我正在开发的 android 应用发出请求
我的设置是:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'rest_framework',
'rest_framework.authtoken',
'rest_auth',
'rest_auth.registration',
'allauth',
'allauth.account',
'allauth.socialaccount',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
)
}
版本:
django-rest-auth==0.9.1
djangorestframework==3.6.2
解决方法很简单:您需要在提出请求时添加 CSRF token
。你会怎么做,具体来说,我们无法回答,因为我们不知道你是如何提出请求的。即 显示一些代码。
您是否正确存储和转发来自 Android 网络库的 cookie?我对Ionic/Android知之甚少,但Django的CSRF检查工作的方式是这样的:
- 检查 body 中是否提供了 CSRF 令牌作为
csrfmiddlewaretoken
- 如果不存在此类参数,请检查名为
csrftoken
的 cookie
- 如果不存在这样的 cookie,则回退到
HTTP_X_CSRFTOKEN
header
Cookie 名称和 header 名称可以在设置中自定义。
那么我的意思是,您在上面使用什么方法发送 CSRF 令牌?在移动设备上,通常很难为请求获取 CSRF 令牌,因为客户端生成表单(在 Web 上,Django 生成表单并注入 CSRF 令牌)。
也就是说,使端点 CSRF 豁免也很常见,而且您似乎正在为这些端点使用第三方库,所以我不确定为什么它需要 CSRF 令牌。您可以查看项目的文档。
另一种可能性是,您已将自己的视图绑定到 URL,并且您到达的是该视图,而不是您正在使用的库中的视图。这很难说。为什么不先使用 DRF Browsable API 尝试请求?
在阅读了 django rest framework 官方文档后,@Todor comment i realize that i should only put TokenAuthentification
in the rest authentication classes because sessionAuthentication
expect a csrf value in the request but android can't give that so i use a token as in the doc 在每个请求中提供了很多帮助,仅此而已!
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
从 DEFAULT_AUTHENTICATION_CLASSES 中删除 'rest_framework.authentication.SessionAuthentication'
,如果您仍然需要 DRF 的可浏览 api 视图,请在 chrome 中使用 ModHeader。
当我尝试在 Apache 服务器上托管我的网站时遇到此错误。
如果我 运行 没有 Apache 服务器 (python manage.py 运行server) 一切都很好。
解决这个错误:
打开 Apache 配置文件 - httpd.conf
添加以下行:
WSGIPassAuthorization On
这是我的快速解决方案,除非您用您的更改分叉 rest-framework 存储库,否则它不适合生产...而且它会禁用 SessionAuthentication 的功能。
如果您要将 api 与无浏览器前端(如移动应用程序)一起使用,它不允许发出跨站点请求(因为没有浏览器可以从中发出请求)可以发出请求,即该应用程序将无法打开 others/you 发送给您的 link 无法在其中传统地浏览网页)然后就这么简单:
要删除该功能,请转到 rest_framework 网站包。在它里面是一个 authentication.py 文件,在它里面,有一个叫做 'SessionAuthentication' 的 class。这里有一个 enforce_csrf() 函数,它通过在请求中不存在 csrf 令牌时引发异常来强制执行 csrf。简单的注释掉它的body,它就不会再关心csrf了。
这是 authentication.py SessionAuthentication class 的样子,请执行以下操作:
class SessionAuthentication(BaseAuthentication):
def authenticate(self, request):
"""
Returns a `User` if the request session currently has a logged in user.
Otherwise returns `None`.
"""
# Get the session-based user from the underlying HttpRequest object
user = getattr(request._request, 'user', None)
# Unauthenticated, CSRF validation not required
if not user or not user.is_active:
return None
self.enforce_csrf(request)
# CSRF passed with authenticated user
return (user, None)
def enforce_csrf(self, request):
"""
Enforce CSRF validation for session based authentication.
"""
##### Comment Out Below: ###########
# check = CSRFCheck()
# # populates request.META['CSRF_COOKIE'], which is used in process_view()
# check.process_request(request)
# reason = check.process_view(request, None, (), {})
# if reason:
# # CSRF failed, bail with explicit error message
# raise exceptions.PermissionDenied('CSRF Failed: %s' % reason)
所以,如果您想知道这是否是个坏主意,因为在大多数情况下,所有请求都是在移动应用程序内专门由移动应用程序有意发出的 app/controlled,它不会在与浏览器相同的环境。用户很难不小心跟随 link 或脚本。请注意,这并不能完全修复漏洞,但发生这种情况的可能性极小,而且很可能不会直接通过移动应用程序发生
我想使用 SessionAuthentication 让当前用户处于静止视图中,我解决了它发送授权 header 每个请求中的令牌值,我正在使用 JSON 网络令牌认证也是
你好,我正在使用 django rest-auth,我在 /password/change/ 中遇到了这个问题,它总是 return csrf 令牌丢失或不正确的问题: 我正在向我正在开发的 android 应用发出请求 我的设置是:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'rest_framework',
'rest_framework.authtoken',
'rest_auth',
'rest_auth.registration',
'allauth',
'allauth.account',
'allauth.socialaccount',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
)
}
版本: django-rest-auth==0.9.1
djangorestframework==3.6.2
解决方法很简单:您需要在提出请求时添加 CSRF token
。你会怎么做,具体来说,我们无法回答,因为我们不知道你是如何提出请求的。即 显示一些代码。
您是否正确存储和转发来自 Android 网络库的 cookie?我对Ionic/Android知之甚少,但Django的CSRF检查工作的方式是这样的:
- 检查 body 中是否提供了 CSRF 令牌作为
csrfmiddlewaretoken
- 如果不存在此类参数,请检查名为
csrftoken
的 cookie
- 如果不存在这样的 cookie,则回退到
HTTP_X_CSRFTOKEN
header
Cookie 名称和 header 名称可以在设置中自定义。
那么我的意思是,您在上面使用什么方法发送 CSRF 令牌?在移动设备上,通常很难为请求获取 CSRF 令牌,因为客户端生成表单(在 Web 上,Django 生成表单并注入 CSRF 令牌)。
也就是说,使端点 CSRF 豁免也很常见,而且您似乎正在为这些端点使用第三方库,所以我不确定为什么它需要 CSRF 令牌。您可以查看项目的文档。
另一种可能性是,您已将自己的视图绑定到 URL,并且您到达的是该视图,而不是您正在使用的库中的视图。这很难说。为什么不先使用 DRF Browsable API 尝试请求?
在阅读了 django rest framework 官方文档后,@Todor comment i realize that i should only put TokenAuthentification
in the rest authentication classes because sessionAuthentication
expect a csrf value in the request but android can't give that so i use a token as in the doc 在每个请求中提供了很多帮助,仅此而已!
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
从 DEFAULT_AUTHENTICATION_CLASSES 中删除 'rest_framework.authentication.SessionAuthentication'
,如果您仍然需要 DRF 的可浏览 api 视图,请在 chrome 中使用 ModHeader。
当我尝试在 Apache 服务器上托管我的网站时遇到此错误。 如果我 运行 没有 Apache 服务器 (python manage.py 运行server) 一切都很好。
解决这个错误: 打开 Apache 配置文件 - httpd.conf 添加以下行:
WSGIPassAuthorization On
这是我的快速解决方案,除非您用您的更改分叉 rest-framework 存储库,否则它不适合生产...而且它会禁用 SessionAuthentication 的功能。
如果您要将 api 与无浏览器前端(如移动应用程序)一起使用,它不允许发出跨站点请求(因为没有浏览器可以从中发出请求)可以发出请求,即该应用程序将无法打开 others/you 发送给您的 link 无法在其中传统地浏览网页)然后就这么简单:
要删除该功能,请转到 rest_framework 网站包。在它里面是一个 authentication.py 文件,在它里面,有一个叫做 'SessionAuthentication' 的 class。这里有一个 enforce_csrf() 函数,它通过在请求中不存在 csrf 令牌时引发异常来强制执行 csrf。简单的注释掉它的body,它就不会再关心csrf了。
这是 authentication.py SessionAuthentication class 的样子,请执行以下操作:
class SessionAuthentication(BaseAuthentication):
def authenticate(self, request):
"""
Returns a `User` if the request session currently has a logged in user.
Otherwise returns `None`.
"""
# Get the session-based user from the underlying HttpRequest object
user = getattr(request._request, 'user', None)
# Unauthenticated, CSRF validation not required
if not user or not user.is_active:
return None
self.enforce_csrf(request)
# CSRF passed with authenticated user
return (user, None)
def enforce_csrf(self, request):
"""
Enforce CSRF validation for session based authentication.
"""
##### Comment Out Below: ###########
# check = CSRFCheck()
# # populates request.META['CSRF_COOKIE'], which is used in process_view()
# check.process_request(request)
# reason = check.process_view(request, None, (), {})
# if reason:
# # CSRF failed, bail with explicit error message
# raise exceptions.PermissionDenied('CSRF Failed: %s' % reason)
所以,如果您想知道这是否是个坏主意,因为在大多数情况下,所有请求都是在移动应用程序内专门由移动应用程序有意发出的 app/controlled,它不会在与浏览器相同的环境。用户很难不小心跟随 link 或脚本。请注意,这并不能完全修复漏洞,但发生这种情况的可能性极小,而且很可能不会直接通过移动应用程序发生
我想使用 SessionAuthentication 让当前用户处于静止视图中,我解决了它发送授权 header 每个请求中的令牌值,我正在使用 JSON 网络令牌认证也是