我有一个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'
),
}
答案 0 :(得分:6)
为什么会收到此错误?
由于您未在设置中定义AUTHENTICATION_CLASSES
,因此DRF使用以下默认身份验证类。
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
)
现在,SessionAuthentication
强制使用CSRF Token
。如果未传递有效的CSRF令牌,则会引发403错误。
如果您正在使用带有
SessionAuthentication
的AJAX样式API,那么您将会这样做 需要确保为任何“不安全”HTTP包含有效的CSRF令牌 方法调用,例如PUT
,PATCH
,POST
或DELETE
请求。
您需要做什么?
由于您使用的是TokenAuthentication
,因此您需要在DRF设置的AUTHENTICATION_CLASSES
中明确定义它。这应解决您的CSRF令牌问题。
答案 1 :(得分:3)
愚蠢的我,我错过了REST设置中的TokenAuthentication
框架:
<强> settings.py 强>
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
现在它的工作正常。
答案 2 :(得分:0)
在发送请求时,您需要传递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令牌,这是出于安全目的。
希望我的回答对您有所帮助。