英文:
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).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论