完整性错误:在表上插入或更新

问题描述 投票:0回答:1

我目前正在开发一个 Web 应用程序,该应用程序使用 Django 作为后端、Django Rest Framework 作为 API、React 作为前端、PostgreSQL 作为数据库。对于用户身份验证,我使用了 SimpleJWT。但是,我遇到了一个问题,我可以通过前端创建用户帐户,但无法使用新创建的帐户登录。控制台中出现一条错误消息,用户信息存在于数据库中。但是,我仍然可以通过前端和 Django Rest Framework 使用不久前创建的几个帐户(来自同一数据库表的所有帐户)登录。
我在 Django 上不断收到此错误:

错误中每次

(user_id)
的括号可能不同

IntegrityError at /api/token/
insert or update on table "token_blacklist_outstandingtoken" violates foreign key constraint "token_blacklist_outs_user_id_83bc629a_fk_auth_user"
DETAIL:  Key (user_id)=(4) is not present in table "auth_user".

这是我的数据库表,我可以通过前端和Rest框架成功登录前3个帐户

settings.py(仅 simpleJWT 部分):

SIMPLE_JWT = {
    "ACCESS_TOKEN_LIFETIME": timedelta(minutes=30),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=90),
    "ROTATE_REFRESH_TOKENS": True,
    "BLACKLIST_AFTER_ROTATION": True,
    "UPDATE_LAST_LOGIN": True,
    # FOR SECURITY REASON (ABOVE)
    "ALGORITHM": "HS256",
    "SIGNING_KEY": SECRET_KEY,
    "VERIFYING_KEY": "",
    "AUDIENCE": None,
    "ISSUER": None,
    "JSON_ENCODER": None,
    "JWK_URL": None,
    "LEEWAY": 0,

    "AUTH_HEADER_TYPES": ("Bearer",),
    "AUTH_HEADER_NAME": "HTTP_AUTHORIZATION",
    "USER_ID_FIELD": "id",
    "USER_ID_CLAIM": "user_id",
    "USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",

    "AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
    "TOKEN_TYPE_CLAIM": "token_type",
    "TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",

    "JTI_CLAIM": "jti",

    "SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
    "SLIDING_TOKEN_LIFETIME": timedelta(minutes=5),
    "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),

    "TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer",
    "TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer",
    "TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer",
    "TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer",
    "SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer",
    "SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer",
}

api/models.py

from django.db import models 
from django.contrib.auth.models import AbstractUser  
class CustomUser(AbstractUser):     
    username = models.CharField(max_length=100)     
    email = models.EmailField(max_length=100, unique=True)      
    USERNAME_FIELD = 'email'     
    REQUIRED_FIELDS = ['username']

api/序列化器.py

from api.models import CustomUser
from rest_framework import serializers
from django.contrib.auth.password_validation import validate_password
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer

class CustomUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = CustomUser
        fields = ('id', 'username', 'email')

class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        
        token['username'] = user.username
        token['email'] = user.email
        return token


class RegisterSerializer(serializers.ModelSerializer):
    password = serializers.CharField(
        write_only=True, required=True, validators=[validate_password])
    confirmed_password = serializers.CharField(write_only=True, required=True)

    class Meta:
        model = CustomUser
        fields = ('email', 'username', 'password', 'confirmed_password')

    def validate(self, attrs):
        if attrs['password'] != attrs['confirmed_password']:
            raise serializers.ValidationError(
                {"password": "Password fields didn't match."})
        return attrs

    def create(self, validated_data):
        user = CustomUser.objects.create(
            username=validated_data['username'],
            email=validated_data['email']
        )
        user.set_password(validated_data['password'])
        user.save()
        return user

api/urls.py

from django.urls import path
from . import views
from .views import MyTokenObtainPairView
from rest_framework_simplejwt.views import(
    TokenObtainPairView,
    TokenRefreshView,
)

urlpatterns = [
    path('', views.getRoutes),

    path('token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    path('register/', views.RegisterView.as_view(), name='auth_register'),
]

api/views.py

from django.http import JsonResponse
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import generics
from api.models import CustomUser
from rest_framework.permissions import AllowAny
from .serializers import MyTokenObtainPairSerializer, RegisterSerializer

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView

class MyTokenObtainPairView(TokenObtainPairView):
    serializer_class = MyTokenObtainPairSerializer

class RegisterView(generics.CreateAPIView):
    queryset = CustomUser.objects.all()
    permission_classes = (AllowAny,)
    serializer_class = RegisterSerializer


@api_view(['GET'])
def getRoutes(request):
    routes = [
    '/api/token',
    '/api/register',
    '/api/token/refresh'
    ]
    return Response(routes)
django postgresql authentication jwt token
1个回答
0
投票

您正在将帐户保存到新的自定义模型

CusomUser
,尽管令牌正在使用内置的 auth_user 模型进行检查,因此会出现错误
DETAIL:  Key (user_id)=(4) is not present in table "auth_user".
,尝试打开
auth_user
表,您很可能只会找到您可以使用 3 个帐户登录,因此可以使用
auth_user
模型作为用户的主要模型并开始保存到该模型,或者更改令牌设置以检查
CustomUser
模型。

© www.soinside.com 2019 - 2024. All rights reserved.