谁能告诉我如何为我的 django 应用程序制作一个正确的登录系统?

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

我需要帮助为我的 Django 课程中的作业构建一个合适的登录系统。我应该构建一个应用程序,用户可以在基于令牌的身份验证中登录,并可以发布目的地并查看它,但我被困在登录部分。我已经成功地正确构建了注册系统,但现在我需要帮助登录。

这是我的登录视图。它不断抛出“NOT NULL约束失败:destination_session.user_id”错误,所以我不知道我做错了什么

def login(request: HttpRequest):
if request.method == "POST":
    email = request.POST.get('email')
    password_hash = request.POST.get('password')

    hasher = hashlib.sha256()
    hasher.update(bytes(password_hash, "UTF-8"))
    password_hash = hasher.hexdigest()

    token = ""
    letters = string.ascii_lowercase
    for _ in range(32):
        token = "".join(random.choice(letters) for _ in range(32))
    session_token = Session.objects.create(token=token)
    response = HttpResponse("Cookie Set")
    
    try: 
        user = User.objects.get(email=email, password_hash=password_hash)
        if user.check_password(password_hash):
            response = redirect("/")
            response.set_cookie('token', token)
            return response
        else:
            return HttpResponse("Invalid password")
    except User.DoesNotExist:
        return Http404({"Invalid email"})
    
return render(request, "destination/login.html")

这是我的模型

from django.db import models
import hashlib

class User(models.Model):
id = models.BigAutoField(primary_key=True)
name = models.TextField()
email = models.EmailField(unique=True)
password_hash = models.TextField()

def check_password(self, hashed_password):
    hasher = hashlib.sha256()
    hasher.update(bytes(self.password_hash, "UTF-8"))
    hashed_password = hasher.hexdigest()
    return self.password_hash == hashed_password

class Session(models.Model):
id = models.BigAutoField(primary_key=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
token = models.TextField()

class Destination(models.Model):
id = models.BigAutoField(primary_key=True)
name = models.TextField()
review = models.TextField()
rating = models.PositiveIntegerField()
share_publicly = models.BooleanField(default=False)
user = models.ForeignKey("User", related_name="destinations", on_delete=models.CASCADE)

这是我的登录表单:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="/login" method="POST">
        <label for="">Email</label>
        <input type="email" name="email" id="email">
        <label for="">Password</label>
        <input type="password" name="password" id="password">
        <button type="submit">Login</button>
    </form>
</body>
</html>

如果有人能发现问题所在或帮助我找到更好的方法,我将不胜感激。另外,我不允许使用内置模块中的身份验证、会话或管理,因此请不要建议它。如果您向我展示如何仅显示登录用户的目的地,那就太好了 xD

django authentication django-models django-views django-forms
1个回答
0
投票

在创建会话之前,您应该首先确保拥有用户对象。

此外,您需要正确检查密码,而无需重新散列密码。

我还可以看到您在表单中使用了字段名称

password
,但在您看来,您正在尝试使用
password_hash
来获取它。这将导致密码哈希为空,因此登录将失败。

您可以更新您的登录视图,例如:

import hashlib
import random
import string
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import User, Session

def login(request):
    if request.method == "POST":
        email = request.POST.get('email')
        password = request.POST.get('password')

        user = User.objects.filter(email=email).first()
        if user and user.check_password(password):
            token = ''.join(random.choice(string.ascii_letters) for _ in range(32))
            session = Session.objects.create(user=user, token=token)
            response = redirect("/")
            response.set_cookie('token', token)
            return response
        return HttpResponse("Invalid email or password")

    return render(request, "destination/login.html")

并更新

check_password
模型中的方法:

class User(models.Model):
    # Fields...

    def check_password(self, password):
        hasher = hashlib.sha256()
        hasher.update(bytes(password, "UTF-8"))
        return self.password_hash == hasher.hexdigest()

最后,为了仅显示登录用户的目的地,您需要从 cookie 中存储的令牌中获取用户。这是显示目的地的视图:

def user_destinations(request):
    token = request.COOKIES.get('token')
    if token:
        session = Session.objects.filter(token=token).first()
        if session:
            destinations = session.user.destinations.all()
            return render(request, "destination/user_destinations.html", {"destinations": destinations})
    return redirect("/login")
© www.soinside.com 2019 - 2024. All rights reserved.