我正在尝试将数据发布到 Django 服务器,以便从 Next.js 应用程序更新用户配置文件;
我对其他路线也有类似的设置,它们工作得很好, 但在这里我收到以下错误:
禁止(未设置 CSRF cookie。):/users/api/update-profile/ [2024年12月15日20:53:02]“发布/users/api/update-profile/HTTP/1.1”403 2855
#settings.py
CSRF_COOKIE_HTTPONLY = False # Allow JavaScript to read the CSRF cookie
#CSRF_USE_SESSIONS = False
CSRF_COOKIE_SAMESITE = 'Lax'
CSRF_COOKIE_SECURE = False
# Ensure these are set correctly
SESSION_COOKIE_SAMESITE = 'Lax' # or 'None' for cross-site
CSRF_COOKIE_SAMESITE = 'Lax' # or 'None' for cross-site
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
CORS_ALLOW_CREDENTIALS = True
#CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOWED_ORIGINS = [
#"http://localhost",
#"http://127.0.0.1",
"http://localhost:3000"
]
CORS_ALLOW_METHODS = [
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
]
CORS_ALLOW_HEADERS = [
'accept',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
]
#views.py
@login_required
def update_profile(request):
if request.method == 'POST':
user = request.user
print('user', user)
# Gender validation
if 'gender' in request.POST:
gender = request.POST.get('gender')
if gender in dict(user.gender_choices):
user.gender = gender
# Username validation
if 'username' in request.POST:
username = request.POST.get('username')
if len(username) <= 50 and not User.objects.exclude(pk=user.pk).filter(username=username).exists():
user.username = username
else:
return JsonResponse({'status': 'error', 'message': 'Invalid or duplicate username'})
# Password validation
if 'password' in request.POST:
password = request.POST.get('password')
if len(password) <= 50:
user.password = make_password(password)
# If you want to keep the user logged in after password change
update_session_auth_hash(request, user)
else:
return JsonResponse({'status': 'error', 'message': 'Password too long'})
# Email validation
if 'email' in request.POST:
email = request.POST.get('email')
try:
validate_email(email)
if not User.objects.exclude(pk=user.pk).filter(email=email).exists():
user.email = email
else:
return JsonResponse({'status': 'error', 'message': 'Email already exists'})
except ValidationError:
return JsonResponse({'status': 'error', 'message': 'Invalid email format'})
# Phone validation
if 'phone' in request.POST:
phone = request.POST.get('phone')
if len(phone) <= 50:
user.phone = phone
# Date of birth validation
if 'date_of_birth' in request.POST:
try:
date_of_birth = datetime.strptime(request.POST.get('date_of_birth'), '%Y-%m-%d').date()
user.date_of_birth = date_of_birth
except ValueError:
return JsonResponse({'status': 'error', 'message': 'Invalid date format. Use YYYY-MM-DD'})
# Zodiac sign validation
if 'zodiac_sign' in request.POST:
zodiac_sign = request.POST.get('zodiac_sign')
if len(zodiac_sign) <= 50:
user.zodiac_sign = zodiac_sign
# Religion validation
if 'religion' in request.POST:
religion = request.POST.get('religion')
if len(religion) <= 100:
user.religion = religion
# Bio validation
if 'bio' in request.POST:
bio = request.POST.get('bio')
if len(bio) <= 500:
user.bio = bio
# Location validation
if 'location' in request.POST:
location = request.POST.get('location')
if len(location) <= 255:
user.location = location
# Profile picture link validation
if 'profile_picture_link' in request.POST:
profile_picture_link = request.POST.get('profile_picture_link')
if len(profile_picture_link) <= 1000:
user.profile_picture_link = profile_picture_link
# Profile picture file validation
if 'profile_picture' in request.FILES:
profile_picture = request.FILES.get('profile_picture')
user.profile_picture = profile_picture
# Onboarded and Premium status (typically not updated via user input)
if 'onboarded' in request.POST:
user.onboarded = request.POST.get('onboarded') == 'True'
if 'is_premium' in request.POST:
user.is_premium = request.POST.get('is_premium') == 'True'
try: # Additional model-level validation
user.save()
return JsonResponse({
'status': 'success',
'message': 'Profile updated successfully',
'updated_fields': list(request.POST.keys())
})
except ValidationError as e:
return JsonResponse({
'status': 'error',
'message': 'Validation failed',
'errors': e.message_dict
})
# If not a POST request, return current user data
return JsonResponse({
'user': {
'username': user.username,
'email': user.email,
# Add other fields as needed
}
})
#updateprofile/route.ts
import { LogInCredentials } from "@/interfaces/user";
import { API_URL } from "@/lib/constants";
import { extractCsrfToken, extractSessionId } from "@/lib/sessionidextractor";
import { NextApiRequest, NextApiResponse } from "next";
import { cookies } from 'next/headers'
import { NextRequest } from "next/server";
export async function POST( req: NextApiRequest, res: NextApiResponse) {
console.log('i am reaching here')
const Cookies = await cookies()
const csrfToken = Cookies.getAll('csrftoken')
const sessionid = Cookies.getAll('sessionid')
console.log('CSRF Token:', csrfToken)
console.log('sessionid:', sessionid)
const profileUpdateResponse = await fetch(`${API_URL}/update-profile/`, {
method: 'POST',
headers:{
'Content-Type': 'application/json',
'X-CSRFToken': `${csrfToken[0].value}`,
'Cookie': `${sessionid[0].value}`
},
body: JSON.stringify(req.body)
});
const responseText = await profileUpdateResponse.text()
//console.log(responseText)
if(profileUpdateResponse.status == 403){
return Response.json({}, {status: 400})
}
if(profileUpdateResponse.status == 401){
console.log('400000000',profileUpdateResponse.status)
return Response.json({}, {status: 400})
}
if(profileUpdateResponse.status == 200 || profileUpdateResponse.status == 302){
return Response.json({}, {status: 200})
}
return Response.json({'response': true},{status: 200})
}
Cookie 处理: 我设置 Cookie 标头的方式可能不正确。通常,您希望将其设置为完整的 cookie 字符串:
const profileUpdateResponse = await fetch(`${API_URL}/update-profile/${requestBody.user_id}/`, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken.value,
'Cookie': `csrftoken=${csrfToken.value}; sessionid=${sessionid.value}`
},
body: JSON.stringify(requestBody)
});