我的仅HTTP cookie被前端接收,但在随后的请求中没有传递到后端,因此破坏了我的身份验证过程。
我想在我的React应用程序中为页面添加身份验证。其中一部分涉及到向我的Django API发出经过身份验证的请求。端点是使用以下身份验证类设置的:
from rest_framework.authentication import TokenAuthentication
from rest_framework.exceptions import AuthenticationFailed
class CookieTokenAuthentication(TokenAuthentication):
def authenticate(self, request):
token = request.COOKIES.get('authToken')
print(f'Cookies: {request.COOKIES}') # printing cookies for debugging
print(f'Token: {token}')
if not token:
raise AuthenticationFailed('No token provided')
token_model = self.get_model()
try:
token_obj = token_model.objects.get(key=token)
except token_model.DoesNotExist:
raise AuthenticationFailed('Invalid token')
if token_obj.expiry < timezone.now():
raise AuthenticationFailed('Token expired')
return (token_obj.user, token_obj)
由于这需要authToken,所以我已经基于默认用户模型生成了authToken。下面是这样做的课程:
authentication_classes = []
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data,
context={'request': request})
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
expiry = timezone.now() + timedelta(days=7)
token, created = Token.objects.get_or_create(user=user)
if not created:
token.expiry = expiry
token.save()
response = Response({
'user_id': user.pk,
'expiry': expiry.isoformat()
})
response.set_cookie(
key='authToken',
value=token.key,
httponly=True,
secure=True,
samesite='None',
expires=expiry,
domain='localhost',
path='/'
)
return response
我可以验证authToken是否发送给用户,因为我可以在用户登录的响应中看到“set_cookie”标头。
我不得不把它做成一个只使用HTTP的cookie,因为我不想受到XSS攻击。显然是什么时候
samesite='False'
你还需要设置
secure=True
,所以我不得不走HTTPS路线。。。
我已经使用OpenSSL生成了一个自签名SSL证书,用于在localhost上进行开发。然后,我将React前端和Django后端配置为使用HTTPS启动。我为Django安装了Django-extensions/Werkzeug并运行了一个指向证书/私钥的命令,为React在“vite.config.js”中指定了HTTPS和证书/密钥。前端和后端服务器都在HTTPS上运行。
然后,我在Chrome中遇到了一些问题,网页不安全,所以我启用了Chrome标志“允许不安全的本地主机”,并将本地主机证书添加到“受信任的根证书颁发机构”。在重新启动缓存并在Chrome中重新加载我的网络应用程序后,我登录了我的网站。当用户登录时,它在HTTPS响应标头中发送了cookie,但随后的请求不包含cookie(我用我在本文中显示的身份验证类检查了这一点,该类打印了请求的cookie)。
我的相关Django设置如下:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'django_filters',
'EstrayaApp.apps.EstrayaappConfig',
'corsheaders',
'rest_framework.authtoken',
'django_extensions',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'EstrayaApp.middleware.TokenExpiryMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'None'
CSRF_COOKIE_SAMESITE = 'None'
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = [
'https://localhost:5173',
'https://localhost:8000',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'EstrayaApp.authentication.CookieTokenAuthentication',
'rest_framework.authentication.TokenAuthentication',
]
}
最后,这里是React函数,它正在发出经过身份验证的请求:
const fetchTargetSkill = async (skill) => {
const response = await fetch(`https://127.0.0.1:8000/usertask-byskill/${skill.id}/`, {
method: 'GET',
credentials: 'include',
});
我觉得我什么都试过了。没有人的帖子是直接相关的,我现在迷路了。任何帮助都将不胜感激,谢谢。