You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django登录认证状态不持久求助:切换页面后用户未保持登录

问题描述

我正在为Django项目实现简单的登录/登出/注册系统,但登录后切换页面时,登录状态无法保持——从登录页跳转到用户主页、首页或其他页面后,request.user.is_authenticated为False。我有一个代码类似的项目可正常运行,因此感到困惑。Django自带的Authenticate也无法工作,所以使用了手动认证逻辑。

相关代码

Views.py

def userCreate(request):
    """
    Creating a new user
    """
    user=User()
    
    user_form = UserForm(request.POST or None, instance=user) 
    if user_form.is_valid():
        user_form.save()
        if user is not None:  
            login(request, user)
        return redirect('user_home', user_id=user.id) 

    return render(request, 'lognom/user_create.html', {'user_form':user_form}) 
    
def userLogIn(request):
    LogInForm_form = LogInForm(request.POST or None)
    if LogInForm_form.is_valid():
        email_field = LogInForm_form.cleaned_data['login_email']
        password_field = LogInForm_form.cleaned_data['login_password']
        try:
            user=User.objects.get(user_email=email_field)
        except:
            error="Invalid user email or password"
            return render(request, 'lognom/login.html', {'LogInForm_form':LogInForm_form, 'error':error})
        if user.password == password_field:
            if user is not None:
                login(request, user)
                return redirect('user_home', user_id=user.id)
            else:
                error="Invalid user email or password"
                return render(request, 'lognom/login.html', {'LogInForm_form':LogInForm_form, 'error':error})
    return render(request, 'lognom/login.html', {'LogInForm_form':LogInForm_form})
    
def userLogOut(request):
    """
    Log out
    """
    logout(request)
    return render(request, 'lognom/logout.html')

models.py

class User(AbstractBaseUser):
    '''
    This table is the User table. Signing up/in uses email and password.
    '''
    ## This field contains the name of the User
    user_name=models.CharField(max_length=100, null=False)
    
## This field contains the first name of the User
    user_firstname=models.CharField(max_length=100, null=False)
    
    ## This field contains the title of the User
    user_title=models.CharField(max_length=30, null=True)
    
    ## This field contains the password of the User 
    password=models.CharField(max_length=100, null=False)
    
    ## This field contains the email of the User
    user_email = models.EmailField(max_length=100, unique=True, null=False)
    
    ## This field contains the sign up date of the user 
    user_sign_up_date=models.DateTimeField(default=datetime.now)
    
    ## This field contains the institution of the user 
    user_institution=models.CharField(max_length=150, null=False)
    
    USERNAME_FIELD='user_email'
    PASSWORD_FIELD='password'
   
    def checkuser(self):
        return (User.get_username(self))
        
    objects=UserManager()   
    class Meta:
        verbose_name = "User"
        ordering = ['user_name']

    def __str__(self):
        return self.user_firstname+" "+self.user_name 

尝试的强制登录代码

def userHome(request, user_id):
    
    user=User.objects.get(id=user_id)
    login(request, user)
    print(request.user.is_authenticated)
    print(request.user)

此时控制台输出True和用户名,但切换到通用首页后,认证状态依然无法保持。


问题分析与解决方法

1. 密码存储逻辑错误

你自定义的User模型手动定义了password=models.CharField(...),但AbstractBaseUser已经内置了密码的哈希存储机制,手动定义的字段会覆盖这个逻辑,导致密码以明文形式存储。而Django的login()函数依赖哈希密码来维持会话,明文密码无法被认证系统识别,因此切换页面后会话失效。

解决步骤:

  • 删除models.py中User模型里的password=models.CharField(max_length=100, null=False)字段;
  • 在userCreate视图中,保存用户前调用set_password()方法处理密码:
    if user_form.is_valid():
        user = user_form.save(commit=False)
        user.set_password(user_form.cleaned_data['password'])
        user.save()
        login(request, user)
        return redirect('user_home', user_id=user.id)
    

2. 登录验证逻辑错误

在userLogIn视图中,你直接对比user.password == password_field,但密码改为哈希存储后,明文对比必然失败。这也是你无法使用Django自带authenticate()函数的原因——该函数默认验证哈希密码。

解决步骤:

  • 替换手动密码对比为user.check_password(password_field):
    # 替换原来的if user.password == password_field:
    if user.check_password(password_field):
        login(request, user)
        return redirect('user_home', user_id=user.id)
    else:
        error="Invalid user email or password"
        return render(request, 'lognom/login.html', {'LogInForm_form':LogInForm_form, 'error':error})
    
  • 或者直接使用Django的authenticate()函数(需要确保AUTH_USER_MODEL配置正确):
    user = authenticate(request, username=email_field, password=password_field)
    if user is not None:
        login(request, user)
        return redirect('user_home', user_id=user.id)
    

3. 自定义User模型配置缺失

你的User模型没有实现AbstractBaseUser要求的必要方法,且存在非标准属性PASSWORD_FIELD,这会导致Django认证系统功能异常。

解决步骤:

  • 删除PASSWORD_FIELD='password'这一行;
  • 添加AbstractBaseUser要求的方法:
    def get_full_name(self):
        return f"{self.user_firstname} {self.user_name}"
    
    def get_short_name(self):
        return self.user_firstname
    
  • 在项目settings.py中配置自定义用户模型:
    AUTH_USER_MODEL = 'your_app_name.User'  # 替换为你的app名称
    

4. 检查中间件配置

确保settings.py的MIDDLEWARE列表中包含以下两个中间件,且顺序正确:

MIDDLEWARE = [
    # 其他中间件...
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    # 其他中间件...
]

这两个中间件是维持用户会话和认证状态的核心,缺失或顺序错误会直接导致登录状态无法跨页面保持。


内容的提问来源于stack exchange,提问作者Lallous97

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 05:22:53