Django & React – 会话认证

huangapple go评论97阅读模式
英文:

Django & React - Session Authentication

问题

我在我的Django - React应用程序中使用会话认证。
但是,没有会话cookie存储在cookie存储中。
(存储了CSRF令牌cookie!)

我清除了本地存储/会话存储和cookies。
我尝试了不同的浏览器。

在前端部分,
我发出登录的POST请求:

  1. axios.defaults.xsrfCookieName = "csrftoken";
  2. axios.defaults.xsrfHeaderName = "X-CSRFToken";
  3. axios.defaults.withCredentials = true;
  4. const client = axios.create({
  5. baseURL: "http://127.0.0.1:8000",
  6. });
  7. function submitLogin(e) {
  8. e.preventDefault();
  9. setIsLoading(true);
  10. client
  11. .post("/login", {
  12. email: email,
  13. password: password,
  14. })
  15. .then(function (res) {
  16. setCurrentUser(true);
  17. window.location.reload(); // 登录后刷新页面
  18. })
  19. .catch(function (error) {
  20. setIsLoading(false);
  21. });
  22. }

我得到了状态码200,用户已登录,一切似乎正常工作。
(在匿名窗口中打开应用程序时,登录不起作用!)

此外,我在开发工具中收到了SameSite属性错误:

指示是否通过指定其SameSite属性在跨站点请求中发送cookie

尽管我在settings.py中设置了所有内容:

  1. SESSION_ENGINE = 'django.contrib.sessions.backends.db'
  2. SESSION_COOKIE_SECURE = False # 在开发中使用HTTP时将其设置为False
  3. SESSION_COOKIE_HTTPONLY = True
  4. SESSION_COOKIE_SAMESITE = 'None' # 如果使用跨站点请求
  5. SESSION_COOKIE_SECURE = True # 如果使用HTTPS

请注意,当设置为

  1. SESSION_COOKIE_SAMESITE = 'lax' 'strict'

并且删除

  1. SESSION_COOKIE_SECURE = True # 如果使用HTTPS

登录不再起作用

我还尝试过不设置SESSION_ENGINE并使用默认值,但这没有任何区别(登录有效,但没有cookie)

在后端,我使用了自定义的User模型。
这是我的UserLogin视图:

  1. class UserLogin(APIView):
  2. permission_classes = (permissions.AllowAny,)
  3. authentication_classes = (SessionAuthentication,)
  4. def post(self, request):
  5. data = request.data
  6. assert validate_email(data)
  7. assert validate_password(data)
  8. serializer = UserLoginSerializer(data=data)
  9. if serializer.is_valid(raise_exception=True):
  10. user = serializer.check_user(data)
  11. login(request, user)
  12. return Response(serializer.data, status=status.HTTP_200_OK)

我在INSTALLED_APPS中包括了corsheaders,在MIDDLEWARE的顶部添加了以下内容:

  1. "corsheaders.middleware.CorsMiddleware",

我还添加了:

  1. CORS_ALLOW_ALL_ORIGINS = True
  2. CORS_ALLOW_CREDENTIALS = True

来自前端到后端的所有其他请求都正常工作!

我也相当确信rest framework已正确配置。我在INSTALLED_APPS中包括了rest_framework,并且:

  1. REST_FRAMEWORK = {
  2. 'DEFAULT_PERMISSION_CLASSES': (
  3. 'rest_framework.permissions.IsAuthenticated',
  4. ),
  5. 'DEFAULT_AUTHENTICATION_CLASSES': (
  6. 'rest_framework.authentication.SessionAuthentication',
  7. ),
  8. }

为什么没有存储会话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:

  1. axios.defaults.xsrfCookieName = "csrftoken";
  2. axios.defaults.xsrfHeaderName = "X-CSRFToken";
  3. axios.defaults.withCredentials = true;
  4. const client = axios.create({
  5. baseURL: "http://127.0.0.1:8000",
  6. });
  7. function submitLogin(e) {
  8. e.preventDefault();
  9. setIsLoading(true);
  10. client
  11. .post("/login", {
  12. email: email,
  13. password: password,
  14. })
  15. .then(function (res) {
  16. setCurrentUser(true);
  17. window.location.reload(); // Refresh the page after login
  18. })
  19. .catch(function (error) {
  20. setIsLoading(false);
  21. });
  22. }

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:

  1. SESSION_ENGINE = 'django.contrib.sessions.backends.db'
  2. SESSION_COOKIE_SECURE = False # Set it to False during development with HTTP
  3. SESSION_COOKIE_HTTPONLY = True
  4. SESSION_COOKIE_SAMESITE = 'None' # If using cross-site requests
  5. SESSION_COOKIE_SECURE = True # If using HTTPS

note that when setting

  1. SESSION_COOKIE_SAMESITE = 'lax' or 'strict'

and removing

  1. 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:

  1. class UserLogin(APIView):
  2. permission_classes = (permissions.AllowAny,)
  3. authentication_classes = (SessionAuthentication,)
  4. def post(self, request):
  5. data = request.data
  6. assert validate_email(data)
  7. assert validate_password(data)
  8. serializer = UserLoginSerializer(data=data)
  9. if serializer.is_valid(raise_exception=True):
  10. user = serializer.check_user(data)
  11. login(request, user)
  12. 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

  1. "corsheaders.middleware.CorsMiddleware",

also I added:

  1. CORS_ALLOW_ALL_ORIGINS = True
  2. 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:

  1. REST_FRAMEWORK = {
  2. 'DEFAULT_PERMISSION_CLASSES': (
  3. 'rest_framework.permissions.IsAuthenticated',
  4. ),
  5. 'DEFAULT_AUTHENTICATION_CLASSES': (
  6. 'rest_framework.authentication.SessionAuthentication',
  7. ),
  8. }

Why is no session cookie stored?

答案1

得分: 1

尝试这样做:
在这里,我移除了重复的行 SESSION_COOKIE_SECURE

  1. SESSION_ENGINE = 'django.contrib.sessions.backends.db'
  2. SESSION_COOKIE_SECURE = True # 如果使用 HTTPS
  3. SESSION_COOKIE_HTTPONLY = True
  4. SESSION_COOKIE_SAMESITE = 'None' # 如果使用跨站请求
英文:

try this way :
in this I remove the duplicate line SESSION_COOKIE_SECURE

  1. SESSION_ENGINE = 'django.contrib.sessions.backends.db'
  2. SESSION_COOKIE_SECURE = True # If using HTTPS
  3. SESSION_COOKIE_HTTPONLY = True
  4. SESSION_COOKIE_SAMESITE = 'None' # If using cross-site requests

答案2

得分: 1

使用SessionAuthentication时,默认情况下Django需要两样东西:

  1. 当已登录用户处于活动状态时,需要cookies-key。
  2. 需要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

  1. cookies-key when a logged-in user is active
  2. 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).

huangapple
  • 本文由 发表于 2023年5月29日 04:55:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76353562.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定