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

