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
相关产品推荐
相关产品推荐

