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

Django中为非User模型(帖子)设置哈希密码后,如何实现编辑时的身份验证?

解决方案:无注册场景下帖子的编辑身份验证

这种无注册、靠帖子密码管理内容的场景很常见,咱们可以基于Django的密码哈希工具来实现安全的验证流程,下面一步步来拆解实现:

1. 先完善帖子模型

首先你的Post模型需要一个字段来存储密码哈希,直接复用Django内置的密码处理逻辑(比你贴的旧版set_password更安全,支持多种现代哈希算法):

from django.db import models
from django.contrib.auth.hashers import check_password, make_password

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    # 和Django User模型的password字段一致,足够存储哈希值
    password = models.CharField(max_length=128, blank=True, null=True)
    # 其他字段比如创建时间、分类等按需添加

    def set_post_password(self, raw_password):
        """给帖子设置密码,自动哈希存储"""
        self.password = make_password(raw_password)
        self.save()

    def check_post_password(self, raw_password):
        """验证输入的密码是否和存储的哈希匹配"""
        return check_password(raw_password, self.password)

2. 创建帖子时处理密码设置

在创建帖子的视图里,用户提交表单时如果填写了密码,就调用上面的set_post_password方法:

from django.shortcuts import render, redirect
from .models import Post
from .forms import PostForm

def create_post(request):
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            raw_password = form.cleaned_data.get('password')
            if raw_password:
                post.set_post_password(raw_password)
            else:
                # 若用户没设密码,直接留空,后续编辑无需验证
                post.password = None
            post.save()
            return redirect('post_detail', pk=post.pk)
    else:
        form = PostForm()
    return render(request, 'create_post.html', {'form': form})

对应的表单要包含密码输入框:

from django import forms
from .models import Post

class PostForm(forms.ModelForm):
    password = forms.CharField(
        widget=forms.PasswordInput(), 
        required=False, 
        help_text="设置密码后,编辑帖子需要验证该密码"
    )

    class Meta:
        model = Post
        fields = ['title', 'content', 'password']

3. 实现编辑时的密码验证流程

核心逻辑是:用户访问编辑页时,先判断帖子是否有密码——没有的话直接进入编辑;有的话先要求输入密码,验证通过后才允许编辑,用会话保存验证状态避免重复输入:

from django.shortcuts import get_object_or_404, render, redirect
from .models import Post
from .forms import PostForm, PostPasswordForm

def edit_post(request, pk):
    post = get_object_or_404(Post, pk=pk)

    # 帖子无密码,直接开放编辑权限
    if not post.password:
        if request.method == 'POST':
            form = PostForm(request.POST, instance=post)
            if form.is_valid():
                form.save()
                return redirect('post_detail', pk=post.pk)
        else:
            form = PostForm(instance=post)
        return render(request, 'edit_post.html', {'form': form, 'post': post})

    # 帖子有密码,处理验证逻辑
    session_key = f'post_{pk}_authenticated'
    if request.method == 'POST':
        # 处理密码验证提交
        if 'password' in request.POST:
            password_form = PostPasswordForm(request.POST)
            if password_form.is_valid():
                raw_password = password_form.cleaned_data['password']
                if post.check_post_password(raw_password):
                    # 验证成功,在会话标记已验证
                    request.session[session_key] = True
                    return redirect('edit_post', pk=pk)
                else:
                    password_form.add_error('password', '密码不正确,请重试')
            return render(request, 'post_password_auth.html', {'password_form': password_form, 'post': post})
        # 已验证状态下处理编辑提交
        elif request.session.get(session_key):
            form = PostForm(request.POST, instance=post)
            if form.is_valid():
                form.save()
                # 编辑完成后可选清除会话标记,下次编辑需重新验证
                del request.session[session_key]
                return redirect('post_detail', pk=post.pk)
        else:
            # 未验证直接提交编辑,重定向到密码验证页
            return redirect('edit_post', pk=pk)
    else:
        # GET请求:检查会话是否已验证
        if request.session.get(session_key):
            form = PostForm(instance=post)
            return render(request, 'edit_post.html', {'form': form, 'post': post})
        else:
            # 未验证,显示密码输入表单
            password_form = PostPasswordForm()
            return render(request, 'post_password_auth.html', {'password_form': password_form, 'post': post})

密码验证表单很简单:

from django import forms

class PostPasswordForm(forms.Form):
    password = forms.CharField(widget=forms.PasswordInput(), label="请输入帖子密码")

4. 配套模板示例

密码验证模板 post_password_auth.html

<h2>验证帖子权限</h2>
<p>要编辑帖子《{{ post.title }}》,请输入你设置的密码:</p>
<form method="post">
    {% csrf_token %}
    {{ password_form.as_p }}
    <button type="submit">验证并编辑</button>
</form>

编辑页面模板 edit_post.html

<h2>编辑帖子《{{ post.title }}》</h2>
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">保存修改</button>
</form>

额外注意事项

  • 用Django内置的make_password和check_password比手动实现哈希更安全,它们会自动处理加盐、算法升级等问题
  • 会话验证状态会在用户关闭浏览器后失效,保证了安全性
  • 如果需要支持修改帖子密码,可以在编辑页添加密码修改字段,调用set_post_password更新即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 12:47:47