Django + DRF:403 FORBIDDEN:CSRF 令牌丢失或不正确
Django + DRF: 403 FORBIDDEN: CSRF token missing or incorrect
我有一个 Android 客户端应用程序尝试使用 Django + DRF 后端进行身份验证。但是,当我尝试登录时,收到以下响应:
403: CSRF Failed: CSRF token missing or incorrect.
请求发送到 http://localhost/rest-auth/google/
,正文如下:
access_token: <the OAuth token from Google>
这可能是什么原因造成的?客户端没有 CSRF 令牌,因为 POST 进行身份验证是客户端和服务器之间发生的第一件事。同样的问题我查了很多以前的问题,都没有找到解决方法
Django端的相关设置是这样的:
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend"
)
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.request",
"django.contrib.auth.context_processors.auth",
"allauth.account.context_processors.account",
"allauth.socialaccount.context_processors.socialaccount"
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'app',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.facebook',
'allauth.socialaccount.providers.google',
'django.contrib.admin',
# REST framework
'rest_framework',
'rest_framework.authtoken',
'rest_auth',
'rest_auth.registration',
)
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated'
),
}
我真傻,我错过了来自 REST 设置的 TokenAuthentication
框架:
settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
现在一切正常。
为什么会出现此错误?
由于您没有在设置中定义 AUTHENTICATION_CLASSES
,DRF 使用以下默认身份验证 类。
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
)
现在,SessionAuthentication
强制使用 CSRF Token
。如果您没有传递有效的 CSRF 令牌,则会引发 403 错误。
If you're using an AJAX style API with SessionAuthentication
, you'll
need to make sure you include a valid CSRF token for any "unsafe" HTTP
method calls, such asPUT
, PATCH
, POST
or DELETE
requests.
那你需要做什么?
由于您正在使用 TokenAuthentication
,您需要在 DRF 设置的 AUTHENTICATION_CLASSES
中明确定义它。这应该可以解决您的 CSRF 令牌问题。
您需要在发送请求时传递 csrf 令牌让我们看一下给定的代码:
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
const check = () => {
const endPoint = '/api/check/'
const csrftoken = getCookie('csrftoken'); // getting the cookie to pass as csrf token
return fetch(baseUrl + endPoint,{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
})
.then(response => {
if (response.ok) {
return response
}
else {
if (response.status === 401 && response.statusText === 'Unauthorized'){ // if it is un authorized then dispatch the logout
dispatch(logout());
}
var error = new Error('Error: '+ response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
var errmess = new Error(error.message);
throw errmess;
})
.then( data => data.json())
.then(data => console.log(data))
.catch(error => console.log(error.message));
}
伙计们记住一件事,无论您是发送 GET PUT 还是 POST 请求,您都需要发送 csrf 令牌,这是出于安全目的。
希望我的回答对您有所帮助
我有一个 Android 客户端应用程序尝试使用 Django + DRF 后端进行身份验证。但是,当我尝试登录时,收到以下响应:
403: CSRF Failed: CSRF token missing or incorrect.
请求发送到 http://localhost/rest-auth/google/
,正文如下:
access_token: <the OAuth token from Google>
这可能是什么原因造成的?客户端没有 CSRF 令牌,因为 POST 进行身份验证是客户端和服务器之间发生的第一件事。同样的问题我查了很多以前的问题,都没有找到解决方法
Django端的相关设置是这样的:
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend"
)
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.request",
"django.contrib.auth.context_processors.auth",
"allauth.account.context_processors.account",
"allauth.socialaccount.context_processors.socialaccount"
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'app',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.facebook',
'allauth.socialaccount.providers.google',
'django.contrib.admin',
# REST framework
'rest_framework',
'rest_framework.authtoken',
'rest_auth',
'rest_auth.registration',
)
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated'
),
}
我真傻,我错过了来自 REST 设置的 TokenAuthentication
框架:
settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
现在一切正常。
为什么会出现此错误?
由于您没有在设置中定义 AUTHENTICATION_CLASSES
,DRF 使用以下默认身份验证 类。
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
)
现在,SessionAuthentication
强制使用 CSRF Token
。如果您没有传递有效的 CSRF 令牌,则会引发 403 错误。
If you're using an AJAX style API with
SessionAuthentication
, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such asPUT
,PATCH
,POST
orDELETE
requests.
那你需要做什么?
由于您正在使用 TokenAuthentication
,您需要在 DRF 设置的 AUTHENTICATION_CLASSES
中明确定义它。这应该可以解决您的 CSRF 令牌问题。
您需要在发送请求时传递 csrf 令牌让我们看一下给定的代码:
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
const check = () => {
const endPoint = '/api/check/'
const csrftoken = getCookie('csrftoken'); // getting the cookie to pass as csrf token
return fetch(baseUrl + endPoint,{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
})
.then(response => {
if (response.ok) {
return response
}
else {
if (response.status === 401 && response.statusText === 'Unauthorized'){ // if it is un authorized then dispatch the logout
dispatch(logout());
}
var error = new Error('Error: '+ response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
var errmess = new Error(error.message);
throw errmess;
})
.then( data => data.json())
.then(data => console.log(data))
.catch(error => console.log(error.message));
}
伙计们记住一件事,无论您是发送 GET PUT 还是 POST 请求,您都需要发送 csrf 令牌,这是出于安全目的。
希望我的回答对您有所帮助