英文:
Django & React - Session Authentication
问题
我在我的Django - React应用程序中使用会话认证。
但是,没有会话cookie存储在cookie存储中。
(存储了CSRF令牌cookie!)
我清除了本地存储/会话存储和cookies。
我尝试了不同的浏览器。
在前端部分,
我发出登录的POST请求:
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.xsrfHeaderName = "X-CSRFToken";
axios.defaults.withCredentials = true;
const client = axios.create({
baseURL: "http://127.0.0.1:8000",
});
function submitLogin(e) {
e.preventDefault();
setIsLoading(true);
client
.post("/login", {
email: email,
password: password,
})
.then(function (res) {
setCurrentUser(true);
window.location.reload(); // 登录后刷新页面
})
.catch(function (error) {
setIsLoading(false);
});
}
我得到了状态码200,用户已登录,一切似乎正常工作。
(在匿名窗口中打开应用程序时,登录不起作用!)
此外,我在开发工具中收到了SameSite属性错误:
指示是否通过指定其SameSite属性在跨站点请求中发送cookie
尽管我在settings.py中设置了所有内容:
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
SESSION_COOKIE_SECURE = False # 在开发中使用HTTP时将其设置为False
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'None' # 如果使用跨站点请求
SESSION_COOKIE_SECURE = True # 如果使用HTTPS
请注意,当设置为
SESSION_COOKIE_SAMESITE = 'lax' 或 'strict'
并且删除
SESSION_COOKIE_SECURE = True # 如果使用HTTPS
登录不再起作用
我还尝试过不设置SESSION_ENGINE并使用默认值,但这没有任何区别(登录有效,但没有cookie)
在后端,我使用了自定义的User模型。
这是我的UserLogin视图:
class UserLogin(APIView):
permission_classes = (permissions.AllowAny,)
authentication_classes = (SessionAuthentication,)
def post(self, request):
data = request.data
assert validate_email(data)
assert validate_password(data)
serializer = UserLoginSerializer(data=data)
if serializer.is_valid(raise_exception=True):
user = serializer.check_user(data)
login(request, user)
return Response(serializer.data, status=status.HTTP_200_OK)
我在INSTALLED_APPS中包括了corsheaders,在MIDDLEWARE的顶部添加了以下内容:
"corsheaders.middleware.CorsMiddleware",
我还添加了:
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = True
来自前端到后端的所有其他请求都正常工作!
我也相当确信rest framework已正确配置。我在INSTALLED_APPS中包括了rest_framework,并且:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
),
}
为什么没有存储会话cookie?
英文:
I am using session authentication in my Django - React application.
But no session cookie is stored in the cookie storage.
(A csrf token cookie is stored!)
I cleared the local storage / session storage and the cookies
I tried with different browsers
On the frontend Part,
I make a post request for the login:
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.xsrfHeaderName = "X-CSRFToken";
axios.defaults.withCredentials = true;
const client = axios.create({
baseURL: "http://127.0.0.1:8000",
});
function submitLogin(e) {
e.preventDefault();
setIsLoading(true);
client
.post("/login", {
email: email,
password: password,
})
.then(function (res) {
setCurrentUser(true);
window.location.reload(); // Refresh the page after login
})
.catch(function (error) {
setIsLoading(false);
});
}
I get a status code 200, user is logged in everything seems to work fine.
(When opening the application in a incognito window the log in is not working!)
Also I get a SameSite attribute error in dev tools:
> Indicate whether to send a cookie in a cross-site request by
> specifying its SameSite attribute
even though I set everything in settings.py:
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
SESSION_COOKIE_SECURE = False # Set it to False during development with HTTP
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'None' # If using cross-site requests
SESSION_COOKIE_SECURE = True # If using HTTPS
note that when setting
SESSION_COOKIE_SAMESITE = 'lax' or 'strict'
and removing
SESSION_COOKIE_SECURE = True # If using HTTPS
the log in no longer works
I also tried without setting the SESSION_ENGINE and using the default but that makes no difference (the login works but no cookie)
On the backend site I use a custom User model
This is my UserLogin View:
class UserLogin(APIView):
permission_classes = (permissions.AllowAny,)
authentication_classes = (SessionAuthentication,)
def post(self, request):
data = request.data
assert validate_email(data)
assert validate_password(data)
serializer = UserLoginSerializer(data=data)
if serializer.is_valid(raise_exception=True):
user = serializer.check_user(data)
login(request, user)
return Response(serializer.data, status=status.HTTP_200_OK)
I included corsheaders in the INSTALLED_APPS and in the MIDDLEWARE right at the top I put
"corsheaders.middleware.CorsMiddleware",
also I added:
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = True
All other requests from frontend to backend work fine!
I am also pretty sure rest framework is configured correctly I included rest_framework in the INSTALLED_APPS and:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
),
}
Why is no session cookie stored?
答案1
得分: 1
尝试这样做:
在这里,我移除了重复的行 SESSION_COOKIE_SECURE
。
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
SESSION_COOKIE_SECURE = True # 如果使用 HTTPS
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'None' # 如果使用跨站请求
英文:
try this way :
in this I remove the duplicate line SESSION_COOKIE_SECURE
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
SESSION_COOKIE_SECURE = True # If using HTTPS
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'None' # If using cross-site requests
答案2
得分: 1
使用SessionAuthentication
时,默认情况下Django需要两样东西:
- 当已登录用户处于活动状态时,需要cookies-key。
- 需要CSRF令牌。
如果这两者不匹配,就会引发错误,因此有文档可以指导正确认证的方法。
当你使用SessionAuthentication
时,你正在使用Django的身份验证,通常需要检查CSRF。所以你必须在X-CSRFToken头部传递CSRF令牌。
这份文档提供了更多关于获取CSRF令牌和在请求中发送它的信息。CSRF令牌保存为名为csrftoken
的cookie,你可以从HTTP响应中获取它。
如果无法获取CSRF cookie,通常意味着你不应该使用SessionAuthentication(而应该使用TokenAuthentication或OAuth 2.0)。
英文:
When you use SessionAuthentication
, by default django requires 2 things
- cookies-key when a logged-in user is active
- csrf-token
If these do not match, then an error is raised, so, there is the documentation to make it authenticate in the correct way.<br>
When you are using SessionAuthentication
, you are using Django's authentication which usually requires CSRF to be checked. So you must pass the CSRF token in the X-CSRFToken header.
This documentation provides more information on retrieving the CSRF token and sending it in requests. The CSRF token is saved as a cookie called csrftoken
that you can retrieve from a HTTP response.
If you cannot retrieve the CSRF cookie, this is usually a sign that you should not be using SessionAuthentication (use TokenAuthentication or OAuth 2.0 instead).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论