Django登录/认证系统无法正常工作

qkf9rpyu  于 2022-12-20  发布在  Go
关注(0)|答案(1)|浏览(193)

我是Django的新手,遇到了一些问题,我尝试在Django中使用postgresql作为主数据库,创建一个简单的登录系统。
问题是,我的身份验证和登录功能显然工作正常,但用户实际上并没有登录,我写了一个自定义消息,让我知道当用户登录,我的索引是保护匿名用户,所以我基本上无法访问。
这段代码来自我的 views.py

@login_required(login_url='signin')
def index(request):
    return render(request, 'index.html')

def signin(request):
    now = datetime.now()
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']

        print(username, password)

        user = UserBackend.authenticate(UserBackend(), username=username, password=password)

        if user is not None:
            login(request, user, backend='core.backends.UserBackend')
            print('Logged In') #### This print/checking is working fine!
            return redirect('/')  
            #return render(request, 'index.html')
        else:
            messages.info(request, 'Invalid Username or Password! Try again')
            return redirect("signin")
    #else:
        return render(request,'signin.html')

    
    #user = auth.authenticate(username=username, password=password)
    return render(request, 'signin.html')

这是我在 models.py 中创建的用户类

class user(AbstractBaseUser):
    id = models.AutoField(primary_key=True)
    username = models.TextField()
    real_name = models.TextField()
    email = models.TextField()
    password = models.TextField()
    description = models.TextField()
    last_login = models.DateField()
    created_at = models.DateField()
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    class Meta:
        managed = False
        db_table = 'user'
        
   
    def __str__(self) -> str:
        return self.username

我的用户后端来自 * backends.py *

class UserBackend(ModelBackend):

    def authenticate(self, **kwargs):
        username = kwargs['username']
        password = kwargs['password']

        print('user: ', username)
        print('pass: ', password)
        #try:
        user_ = user.objects.get(username=username)
        
        try:
            print(user_.check_password(password))
            if user_.check_password(password) is True:
                return user_
        except user.DoesNotExist:
            pass

        def get_user(self, user_id):
            try:
                return user.objects.get(pk=user_id)
            except user.DoesNotExist:
                return None

我试着将 * views.py * 的回报率更改为

return redirect(request.GET.get('next'))

但仍然不工作:(
我该怎么办?

bpsygsoo

bpsygsoo1#

关键点,是你如何使用你的后端。虽然,让我们从头开始...
从你的模型开始,你不必要地覆盖了很多字段。Django的AbstractUser包含了你正在创建的这些字段。事实上,模型包含了以下字段,并在适当的地方使用了验证器:
1.用户名
1.名
1.姓
1.电子邮件

  1. is_staff作为默认值false
  2. is_active作为默认值true
    1.日期_加入为默认值timezone.now()
    1.上次登录
    1.内置函数get_full_name(相当于real_name字段)
    另外,id = models.AutoField(primary_key=True)也不是必需的Django默认会为每个模型自动创建这种类型的字段。大多数时候,当你想要一个不同类型的字段作为PK时,会使用这种字段。因此,一个简单的模型就能满足你的要求:
from django.db import models
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    description = models.TextField()

后端非常简单,检查凭据,如果一切正确,则返回一个User对象示例。ModelBackend已经定义了一个get_user方法。

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.hashers import check_password
from django.contrib.auth import get_user_model

User = get_user_model()

class UserBackend(ModelBackend):
    def authenticate(self, request, **kwargs):
        username = kwargs['username']
        password = kwargs['password']
        
        try:
            user = User.objects.get(username=username)
            pwd_valid = check_password(password, user.password)
            
            if  pwd_valid:
                return user
            else:
                return None
            
        except User.DoesNotExist:
            return None

现在,关于如何使用它。引用文档:
在后台,Django维护了一个"验证后端"列表,它会检查验证。当有人调用django. contrib. auth. authenticate()时,Django会尝试在所有的验证后端进行验证。如果第一个验证方法失败,Django会尝试第二个,依此类推,直到所有的后端都尝试过。
要使用的身份验证后端列表在AUTHENTICATION_BACKENDS设置中指定。这应该是一个Python路径名列表,指向知道如何进行身份验证的Python类。这些类可以位于Python路径上的任何位置。
So, first we need to add AUTHENTICATION_BACKENDS in settings.py:

AUTH_USER_MODEL = 'core.User'
LOGIN_URL = '/signin'

AUTHENTICATION_BACKENDS = [
    'core.auth.backends.UserBackend', 
    'django.contrib.auth.backends.ModelBackend'
]

And lastly in views.py, we call the functions exactly as you would in a normal login function:

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import login, authenticate
from django.contrib import messages

# Create your views here.
@login_required
def index(request):
    return render(request, 'index.html')

def signin(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']

        user = authenticate(request, username=username, password=password)

        if user is not None:
            login(request, user)
            # Confirm that backend is UserBackend
            print(user.backend)
            return redirect('core:index')
        else:
            messages.info(request, 'Invalid Username or Password! Try again')
            return redirect("core:signin")

    return render(request, 'signin.html')

相关问题