|
|
|
|
@ -1,59 +1,164 @@
|
|
|
|
|
# 导入日志模块,用于记录运行时的信息和错误
|
|
|
|
|
import logging
|
|
|
|
|
# Django 国际化工具,`gettext_lazy` 用于延迟翻译(适合模块级字符串)
|
|
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
# Django 配置项,用于访问 settings.py 中的设置
|
|
|
|
|
from django.conf import settings
|
|
|
|
|
# Django 认证系统核心模块
|
|
|
|
|
from django.contrib import auth
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 认证相关常量(如重定向字段名)
|
|
|
|
|
from django.contrib.auth import REDIRECT_FIELD_NAME
|
|
|
|
|
# 获取当前用户模型的快捷方式
|
|
|
|
|
from django.contrib.auth import get_user_model
|
|
|
|
|
# 用户登出功能
|
|
|
|
|
from django.contrib.auth import logout
|
|
|
|
|
# Django 内置的认证表单(如登录表单)
|
|
|
|
|
from django.contrib.auth.forms import AuthenticationForm
|
|
|
|
|
# 密码哈希工具
|
|
|
|
|
from django.contrib.auth.hashers import make_password
|
|
|
|
|
# HTTP 响应类(重定向、禁止访问等)
|
|
|
|
|
from django.http import HttpResponseRedirect, HttpResponseForbidden
|
|
|
|
|
# HTTP 请求和响应的类型提示(可选,用于类型检查)
|
|
|
|
|
from django.http.request import HttpRequest
|
|
|
|
|
from django.http.response import HttpResponse
|
|
|
|
|
# 快捷函数(如获取对象或返回 404)
|
|
|
|
|
from django.shortcuts import get_object_or_404
|
|
|
|
|
# 渲染模板的快捷方式
|
|
|
|
|
from django.shortcuts import render
|
|
|
|
|
# URL 反转工具(通过名称生成 URL)
|
|
|
|
|
from django.urls import reverse
|
|
|
|
|
# 视图装饰器工具
|
|
|
|
|
from django.utils.decorators import method_decorator
|
|
|
|
|
# URL 安全验证工具(防止重定向攻击)
|
|
|
|
|
from django.utils.http import url_has_allowed_host_and_scheme
|
|
|
|
|
# 基础视图类
|
|
|
|
|
from django.views import View
|
|
|
|
|
# 缓存控制装饰器(禁用缓存)
|
|
|
|
|
from django.views.decorators.cache import never_cache
|
|
|
|
|
# CSRF 防护装饰器
|
|
|
|
|
from django.views.decorators.csrf import csrf_protect
|
|
|
|
|
# 敏感参数标记(如密码字段)
|
|
|
|
|
from django.views.decorators.debug import sensitive_post_parameters
|
|
|
|
|
# 通用视图类(表单视图、重定向视图)
|
|
|
|
|
from django.views.generic import FormView, RedirectView
|
|
|
|
|
|
|
|
|
|
# 项目自定义工具
|
|
|
|
|
from djangoblog.utils import send_email, get_sha256, get_current_site, generate_code, delete_sidebar_cache
|
|
|
|
|
# 当前应用的工具模块
|
|
|
|
|
from . import utils
|
|
|
|
|
# 当前应用的表单(注册、登录、忘记密码等)
|
|
|
|
|
from .forms import RegisterForm, LoginForm, ForgetPasswordForm, ForgetPasswordCodeForm
|
|
|
|
|
# 当前应用的模型(博客用户)
|
|
|
|
|
from .models import BlogUser
|
|
|
|
|
|
|
|
|
|
# 初始化日志记录器(__name__ 表示当前模块名)
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
=======
|
|
|
|
|
from django.contrib.auth import REDIRECT_FIELD_NAME # 登录后重定向字段名常量
|
|
|
|
|
from django.contrib.auth import get_user_model # 获取项目配置的用户模型
|
|
|
|
|
from django.contrib.auth import logout # 登出功能函数
|
|
|
|
|
from django.contrib.auth.forms import AuthenticationForm # Django内置登录表单
|
|
|
|
|
from django.contrib.auth.hashers import make_password # 密码哈希处理函数
|
|
|
|
|
from django.http import HttpResponseRedirect, HttpResponseForbidden # HTTP响应类
|
|
|
|
|
from django.http.request import HttpRequest
|
|
|
|
|
from django.http.response import HttpResponse
|
|
|
|
|
from django.shortcuts import get_object_or_404, render # 快捷函数
|
|
|
|
|
from django.urls import reverse # URL反向解析
|
|
|
|
|
from django.utils.decorators import method_decorator # 类视图装饰器工具
|
|
|
|
|
from django.utils.http import url_has_allowed_host_and_scheme # 验证重定向URL安全性
|
|
|
|
|
from django.views import View # 基础视图类
|
|
|
|
|
from django.views.decorators.cache import never_cache # 禁止缓存装饰器
|
|
|
|
|
from django.views.decorators.csrf import csrf_protect # CSRF保护装饰器
|
|
|
|
|
from django.views.decorators.debug import sensitive_post_parameters # 敏感参数保护装饰器
|
|
|
|
|
from django.views.generic import FormView, RedirectView # 通用类视图
|
|
|
|
|
|
|
|
|
|
from djangoblog.utils import (send_email, get_sha256, get_current_site,
|
|
|
|
|
generate_code, delete_sidebar_cache) # 项目工具函数
|
|
|
|
|
from . import utils # 当前应用工具函数(验证码相关)
|
|
|
|
|
from .forms import (RegisterForm, LoginForm, ForgetPasswordForm,
|
|
|
|
|
ForgetPasswordCodeForm) # 当前应用表单类
|
|
|
|
|
from .models import BlogUser # 自定义用户模型
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__) # 初始化日志记录器
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create your views here.
|
|
|
|
|
|
|
|
|
|
# 注册视图类(继承自 FormView,处理表单提交)
|
|
|
|
|
class RegisterView(FormView):
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 指定使用的表单类
|
|
|
|
|
form_class = RegisterForm
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
template_name = 'account/registration_form.html'
|
|
|
|
|
# 使用装饰器确保视图禁用缓存(never_cache)并启用 CSRF 防护
|
|
|
|
|
=======
|
|
|
|
|
template_name = 'account/registration_form.html'#处理用户注册逻辑,指定表单类RegisterForm和模板account/registration_form.html。
|
|
|
|
|
|
|
|
|
|
>>>>>>> LXY_branch
|
|
|
|
|
@method_decorator(csrf_protect)
|
|
|
|
|
def dispatch(self, *args, **kwargs):
|
|
|
|
|
# 调用父类方法处理请求
|
|
|
|
|
=======
|
|
|
|
|
"""
|
|
|
|
|
用户注册类视图,继承自FormView(处理表单提交的通用视图)
|
|
|
|
|
负责用户注册表单展示、数据验证、发送验证邮件及注册结果跳转
|
|
|
|
|
"""
|
|
|
|
|
form_class = RegisterForm # 指定使用的注册表单
|
|
|
|
|
template_name = 'account/registration_form.html' # 注册页面模板路径
|
|
|
|
|
|
|
|
|
|
@method_decorator(csrf_protect) # 为视图添加CSRF保护
|
|
|
|
|
def dispatch(self, *args, **kwargs):
|
|
|
|
|
"""重写分发方法,添加装饰器后调用父类逻辑"""
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
return super(RegisterView, self).dispatch(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
# 表单验证通过后的处理逻辑
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 再次检查表单有效性(冗余,因为 FormView 已验证)
|
|
|
|
|
if form.is_valid():
|
|
|
|
|
user = form.save(False)
|
|
|
|
|
user.is_active = False
|
|
|
|
|
user.source = 'Register'
|
|
|
|
|
user.save(True)
|
|
|
|
|
# 保存用户对象(但暂不激活 is_active=False)
|
|
|
|
|
user = form.save(False)
|
|
|
|
|
user.is_active = False# 用户需验证邮箱后才能登录
|
|
|
|
|
user.source = 'Register' # 标记用户来源为注册
|
|
|
|
|
user.save(True)# 实际保存到数据库
|
|
|
|
|
|
|
|
|
|
# 获取当前站点域名(用于生成验证链接)
|
|
|
|
|
site = get_current_site().domain
|
|
|
|
|
# 生成签名(双重 SHA256 哈希,用于验证链接安全性)
|
|
|
|
|
sign = get_sha256(get_sha256(settings.SECRET_KEY + str(user.id)))
|
|
|
|
|
# 开发环境使用本地地址(避免因域名未配置导致链接失效)
|
|
|
|
|
if settings.DEBUG:
|
|
|
|
|
site = '127.0.0.1:8000'
|
|
|
|
|
|
|
|
|
|
# 生成验证结果的 URL(如 /account/result/?type=validation&id=1&sign=abc123)
|
|
|
|
|
path = reverse('account:result')
|
|
|
|
|
url = "http://{site}{path}?type=validation&id={id}&sign={sign}".format(
|
|
|
|
|
site=site, path=path, id=user.id, sign=sign)
|
|
|
|
|
# 构造邮件内容(包含验证链接)
|
|
|
|
|
=======
|
|
|
|
|
"""表单验证通过后执行的逻辑(注册核心流程)"""
|
|
|
|
|
if form.is_valid():
|
|
|
|
|
# 1. 暂存用户数据,不立即保存(is_active设为False,需邮箱验证后激活)
|
|
|
|
|
user = form.save(False)
|
|
|
|
|
user.is_active = False # 初始状态:未激活(需邮箱验证)
|
|
|
|
|
user.source = 'Register' # 标记注册来源为“前台注册”
|
|
|
|
|
user.save(True) # 保存用户到数据库
|
|
|
|
|
|
|
|
|
|
# 2. 生成邮箱验证链接(包含签名,防止篡改)
|
|
|
|
|
site = get_current_site().domain # 获取当前站点域名
|
|
|
|
|
# 双重SHA256加密:用SECRET_KEY+用户ID生成签名,确保链接安全性
|
|
|
|
|
sign = get_sha256(get_sha256(settings.SECRET_KEY + str(user.id)))
|
|
|
|
|
|
|
|
|
|
# 开发环境下替换域名(适配本地测试)
|
|
|
|
|
if settings.DEBUG:
|
|
|
|
|
site = '127.0.0.1:8000'
|
|
|
|
|
# 反向解析结果页URL,拼接完整验证链接
|
|
|
|
|
path = reverse('account:result')
|
|
|
|
|
url = "http://{site}{path}?type=validation&id={id}&sign={sign}".format(
|
|
|
|
|
site=site, path=path, id=user.id, sign=sign)
|
|
|
|
|
|
|
|
|
|
# 3. 构造验证邮件内容并发送
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
content = """
|
|
|
|
|
<p>请点击下面链接验证您的邮箱</p>
|
|
|
|
|
|
|
|
|
|
@ -64,141 +169,421 @@ class RegisterView(FormView):
|
|
|
|
|
如果上面链接无法打开,请将此链接复制至浏览器。
|
|
|
|
|
{url}
|
|
|
|
|
""".format(url=url)
|
|
|
|
|
# 发送验证邮件
|
|
|
|
|
send_email(
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
emailto=[
|
|
|
|
|
user.email,
|
|
|
|
|
user.email, # 收件人列表
|
|
|
|
|
],
|
|
|
|
|
title='验证您的电子邮箱',
|
|
|
|
|
content=content)
|
|
|
|
|
|
|
|
|
|
title='验证您的电子邮箱', # 邮件标题
|
|
|
|
|
content=content)# 邮件正文
|
|
|
|
|
# 重定向到注册结果页面(附带用户 ID)
|
|
|
|
|
url = reverse('accounts:result') + \
|
|
|
|
|
'?type=register&id=' + str(user.id)
|
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
|
else:
|
|
|
|
|
# 表单无效时重新渲染表单(显示错误信息)
|
|
|
|
|
return self.render_to_response({
|
|
|
|
|
'form': form
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
})
|
|
|
|
|
=======
|
|
|
|
|
emailto=[user.email], # 收件人邮箱(新注册用户的邮箱)
|
|
|
|
|
title='验证您的电子邮箱', # 邮件标题
|
|
|
|
|
content=content # 邮件HTML内容
|
|
|
|
|
)
|
|
|
|
|
=======
|
|
|
|
|
})#form_valid方法中,保存用户并设置为非活跃状态,生成邮箱验证链接并发送验证邮件,最后重定向到结果页。
|
|
|
|
|
>>>>>>> LXY_branch
|
|
|
|
|
|
|
|
|
|
# 4. 跳转到注册结果页(提示用户查收验证邮件)
|
|
|
|
|
url = reverse('accounts:result') + f'?type=register&id={str(user.id)}'
|
|
|
|
|
return HttpResponseRedirect(url)
|
|
|
|
|
else:
|
|
|
|
|
# 表单验证失败,重新渲染表单并显示错误
|
|
|
|
|
return self.render_to_response({'form': form})
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 登出视图,继承自RedirectView,重定向到登录页面
|
|
|
|
|
class LogoutView(RedirectView):
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 登出后重定向的URL
|
|
|
|
|
url = '/login/'
|
|
|
|
|
# 使用never_cache装饰器确保视图不会被缓存
|
|
|
|
|
=======
|
|
|
|
|
url = '/login/'#处理用户登出,登出后重定向到/login/
|
|
|
|
|
|
|
|
|
|
>>>>>>> LXY_branch
|
|
|
|
|
@method_decorator(never_cache)
|
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
|
|
|
# 调用父类的dispatch方法处理请求
|
|
|
|
|
=======
|
|
|
|
|
"""
|
|
|
|
|
用户登出类视图,继承自RedirectView(处理重定向的通用视图)
|
|
|
|
|
负责清除用户会话、缓存,并重定向到登录页
|
|
|
|
|
"""
|
|
|
|
|
url = '/login/' # 登出后默认重定向地址(登录页)
|
|
|
|
|
|
|
|
|
|
@method_decorator(never_cache) # 禁止缓存登出页面,避免浏览器缓存导致的问题
|
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
|
|
|
"""重写分发方法,添加装饰器后调用父类逻辑"""
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
return super(LogoutView, self).dispatch(request, *args, **kwargs)
|
|
|
|
|
|
|
|
|
|
# 处理GET请求
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 执行登出操作
|
|
|
|
|
logout(request)
|
|
|
|
|
# 删除侧边栏缓存
|
|
|
|
|
delete_sidebar_cache()
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 调用父类的get方法完成重定向
|
|
|
|
|
return super(LogoutView, self).get(request, *args, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=======
|
|
|
|
|
"""处理GET请求(登出核心逻辑)"""
|
|
|
|
|
logout(request) # 清除用户会话,实现登出
|
|
|
|
|
delete_sidebar_cache() # 删除侧边栏缓存(可能存储了用户相关信息)
|
|
|
|
|
return super(LogoutView, self).get(request, *args, **kwargs) # 执行重定向
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
=======
|
|
|
|
|
return super(LogoutView, self).get(request, *args, **kwargs)#get方法中调用logout登出用户,删除侧边栏缓存后完成重定向
|
|
|
|
|
>>>>>>> LXY_branch
|
|
|
|
|
|
|
|
|
|
# 登录视图,继承自FormView
|
|
|
|
|
class LoginView(FormView):
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 使用的表单类
|
|
|
|
|
form_class = LoginForm
|
|
|
|
|
# 模板文件路径
|
|
|
|
|
template_name = 'account/login.html'
|
|
|
|
|
# 登录成功后跳转的URL
|
|
|
|
|
success_url = '/'
|
|
|
|
|
# 重定向字段名
|
|
|
|
|
redirect_field_name = REDIRECT_FIELD_NAME
|
|
|
|
|
# 登录会话有效期(一个月的时间,单位:秒)
|
|
|
|
|
login_ttl = 2626560 # 一个月的时间
|
|
|
|
|
|
|
|
|
|
@method_decorator(sensitive_post_parameters('password'))
|
|
|
|
|
# 使用多个装饰器装饰dispatch方法
|
|
|
|
|
@method_decorator(sensitive_post_parameters('password'))# 标记密码参数为敏感信息
|
|
|
|
|
@method_decorator(csrf_protect) # 启用CSRF保护
|
|
|
|
|
@method_decorator(never_cache)# 禁止缓存
|
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
|
|
|
# 调用父类的dispatch方法处理请求
|
|
|
|
|
=======
|
|
|
|
|
"""
|
|
|
|
|
用户登录类视图,继承自FormView
|
|
|
|
|
负责登录表单展示、数据验证、用户认证、记住登录状态及重定向
|
|
|
|
|
"""
|
|
|
|
|
form_class = LoginForm # 指定使用的自定义登录表单
|
|
|
|
|
template_name = 'account/login.html' # 登录页面模板路径
|
|
|
|
|
success_url = '/' # 登录成功默认重定向地址(首页)
|
|
|
|
|
redirect_field_name = REDIRECT_FIELD_NAME # 重定向字段名(默认next)
|
|
|
|
|
login_ttl = 2626560 # “记住登录”状态的有效期(秒),约等于1个月
|
|
|
|
|
|
|
|
|
|
# 为视图添加多重装饰器:敏感参数保护、CSRF保护、禁止缓存
|
|
|
|
|
@method_decorator(sensitive_post_parameters('password')) # 保护密码参数,避免日志泄露
|
|
|
|
|
@method_decorator(csrf_protect)
|
|
|
|
|
@method_decorator(never_cache)
|
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
|
|
|
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
return super(LoginView, self).dispatch(request, *args, **kwargs)
|
|
|
|
|
|
|
|
|
|
# 获取模板上下文数据
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 从GET参数中获取重定向URL
|
|
|
|
|
=======
|
|
|
|
|
"""添加额外上下文数据(重定向地址)到模板"""
|
|
|
|
|
# 获取URL中的重定向参数(如登录前访问的受保护页面)
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
redirect_to = self.request.GET.get(self.redirect_field_name)
|
|
|
|
|
# 如果不存在则设置为根路径
|
|
|
|
|
if redirect_to is None:
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
redirect_to = '/'
|
|
|
|
|
# 将重定向URL添加到上下文
|
|
|
|
|
kwargs['redirect_to'] = redirect_to
|
|
|
|
|
# 调用父类方法获取其他上下文数据
|
|
|
|
|
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
return super(LoginView, self).get_context_data(**kwargs)
|
|
|
|
|
|
|
|
|
|
# 表单验证通过后的处理
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
|
# 重新创建认证表单(这里可能有逻辑问题,因为form已经传入)
|
|
|
|
|
=======
|
|
|
|
|
redirect_to = '/' # 默认重定向到首页
|
|
|
|
|
kwargs['redirect_to'] = redirect_to # 将重定向地址传入模板上下文
|
|
|
|
|
return super(LoginView, self).get_context_data(** kwargs)
|
|
|
|
|
|
|
|
|
|
=======
|
|
|
|
|
return super(LoginView, self).get_context_data(**kwargs)#处理用户登录逻辑,指定表单类LoginForm、模板account / login.html和成功后重定向地址 /
|
|
|
|
|
>>>>>>> LXY_branch
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
|
"""表单验证通过后执行的逻辑(登录核心流程)"""
|
|
|
|
|
# 用Django内置AuthenticationForm重新验证(确保认证逻辑符合默认规范)
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
form = AuthenticationForm(data=self.request.POST, request=self.request)
|
|
|
|
|
|
|
|
|
|
# 再次验证表单
|
|
|
|
|
if form.is_valid():
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 删除侧边栏缓存
|
|
|
|
|
delete_sidebar_cache()
|
|
|
|
|
# 记录日志
|
|
|
|
|
logger.info(self.redirect_field_name)
|
|
|
|
|
|
|
|
|
|
# 登录用户
|
|
|
|
|
auth.login(self.request, form.get_user())
|
|
|
|
|
# 如果用户选择了"记住我"
|
|
|
|
|
=======
|
|
|
|
|
delete_sidebar_cache() # 删除侧边栏缓存(更新用户登录状态)
|
|
|
|
|
logger.info(self.redirect_field_name) # 日志记录重定向字段名
|
|
|
|
|
|
|
|
|
|
# 执行登录:将用户信息存入会话
|
|
|
|
|
auth.login(self.request, form.get_user())
|
|
|
|
|
# 处理“记住我”功能:若勾选,设置会话有效期为1个月
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
if self.request.POST.get("remember"):
|
|
|
|
|
# 设置较长的会话过期时间
|
|
|
|
|
self.request.session.set_expiry(self.login_ttl)
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 调用父类方法处理成功跳转
|
|
|
|
|
=======
|
|
|
|
|
# 调用父类form_valid,执行重定向
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
return super(LoginView, self).form_valid(form)
|
|
|
|
|
# return HttpResponseRedirect('/')
|
|
|
|
|
else:
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 表单无效,重新渲染表单并显示错误
|
|
|
|
|
return self.render_to_response({
|
|
|
|
|
'form': form
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
})
|
|
|
|
|
# 获取成功后的跳转URL
|
|
|
|
|
=======
|
|
|
|
|
})#form_valid方法中验证表单,登录用户并根据“记住我”选项设置会话过期时间
|
|
|
|
|
|
|
|
|
|
>>>>>>> LXY_branch
|
|
|
|
|
def get_success_url(self):
|
|
|
|
|
|
|
|
|
|
# 从POST参数中获取重定向URL
|
|
|
|
|
redirect_to = self.request.POST.get(self.redirect_field_name)
|
|
|
|
|
# 检查URL是否安全
|
|
|
|
|
if not url_has_allowed_host_and_scheme(
|
|
|
|
|
url=redirect_to, allowed_hosts=[
|
|
|
|
|
self.request.get_host()]):
|
|
|
|
|
# 如果不安全则使用默认成功URL
|
|
|
|
|
redirect_to = self.success_url
|
|
|
|
|
return redirect_to
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
=======
|
|
|
|
|
# 表单验证失败(如密码错误),重新渲染表单并显示错误
|
|
|
|
|
return self.render_to_response({'form': form})
|
|
|
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
|
"""自定义登录成功后的重定向地址(优先使用URL中的next参数)"""
|
|
|
|
|
# 获取POST请求中的重定向地址(用户登录前尝试访问的页面)
|
|
|
|
|
redirect_to = self.request.POST.get(self.redirect_field_name)
|
|
|
|
|
# 验证重定向地址的安全性:避免跳转到外部恶意网站
|
|
|
|
|
if not url_has_allowed_host_and_scheme(
|
|
|
|
|
url=redirect_to, allowed_hosts=[self.request.get_host()]):
|
|
|
|
|
redirect_to = self.success_url # 不安全则使用默认重定向地址
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
return redirect_to
|
|
|
|
|
=======
|
|
|
|
|
return redirect_to#get_success_url方法处理登录后的重定向地址,确保其安全性
|
|
|
|
|
>>>>>>> LXY_branch
|
|
|
|
|
|
|
|
|
|
# 账户操作结果页面(如注册成功、邮箱验证等)
|
|
|
|
|
def account_result(request):
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 从GET参数中获取类型和用户ID
|
|
|
|
|
type = request.GET.get('type')
|
|
|
|
|
id = request.GET.get('id')
|
|
|
|
|
|
|
|
|
|
# 获取用户对象,如果不存在返回404
|
|
|
|
|
user = get_object_or_404(get_user_model(), id=id)
|
|
|
|
|
logger.info(type)
|
|
|
|
|
# 如果用户已激活,直接重定向到首页
|
|
|
|
|
if user.is_active:
|
|
|
|
|
return HttpResponseRedirect('/')
|
|
|
|
|
# 检查类型参数是否有效
|
|
|
|
|
=======
|
|
|
|
|
"""
|
|
|
|
|
账号操作结果视图函数(函数视图)
|
|
|
|
|
处理注册成功提示、邮箱验证逻辑,并展示结果页面
|
|
|
|
|
"""
|
|
|
|
|
# 从URL参数中获取操作类型(register/validation)和用户ID
|
|
|
|
|
type = request.GET.get('type')
|
|
|
|
|
id = request.GET.get('id')
|
|
|
|
|
|
|
|
|
|
# 获取对应的用户,若不存在则返回404
|
|
|
|
|
user = get_object_or_404(get_user_model(), id=id)
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
logger.info(type) # 日志记录操作类型
|
|
|
|
|
|
|
|
|
|
# 若用户已激活,直接重定向到首页(避免重复验证)
|
|
|
|
|
=======
|
|
|
|
|
logger.info(type)#处理注册和邮箱验证的结果逻辑,根据type参数区分场景:
|
|
|
|
|
>>>>>>> LXY_branch
|
|
|
|
|
if user.is_active:
|
|
|
|
|
return HttpResponseRedirect('/')
|
|
|
|
|
|
|
|
|
|
# 处理合法的操作类型(注册成功提示/邮箱验证)
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
if type and type in ['register', 'validation']:
|
|
|
|
|
if type == 'register':
|
|
|
|
|
# 注册成功:提示用户查收验证邮件
|
|
|
|
|
content = '''
|
|
|
|
|
恭喜您注册成功,一封验证邮件已经发送到您的邮箱,请验证您的邮箱后登录本站。
|
|
|
|
|
'''
|
|
|
|
|
title = '注册成功'
|
|
|
|
|
else:
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 生成验证签名
|
|
|
|
|
=======
|
|
|
|
|
# 邮箱验证:验证签名是否正确,正确则激活用户
|
|
|
|
|
# 重新计算签名,与URL中的签名对比(防止链接篡改)
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
c_sign = get_sha256(get_sha256(settings.SECRET_KEY + str(user.id)))
|
|
|
|
|
# 获取请求中的签名
|
|
|
|
|
sign = request.GET.get('sign')
|
|
|
|
|
# 验证签名是否匹配
|
|
|
|
|
if sign != c_sign:
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
return HttpResponseForbidden()
|
|
|
|
|
# 激活用户账户
|
|
|
|
|
user.is_active = True
|
|
|
|
|
user.save()
|
|
|
|
|
# 验证成功提示内容
|
|
|
|
|
=======
|
|
|
|
|
return HttpResponseForbidden() # 签名不匹配,返回403禁止访问
|
|
|
|
|
# 激活用户:将is_active设为True
|
|
|
|
|
user.is_active = True
|
|
|
|
|
user.save()
|
|
|
|
|
# 验证成功:提示用户可登录
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
content = '''
|
|
|
|
|
恭喜您已经成功的完成邮箱验证,您现在可以使用您的账号来登录本站。
|
|
|
|
|
'''
|
|
|
|
|
title = '验证成功'
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 渲染结果页面
|
|
|
|
|
=======
|
|
|
|
|
# 渲染结果页面,传递标题和内容
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
return render(request, 'account/result.html', {
|
|
|
|
|
'title': title,
|
|
|
|
|
'content': content
|
|
|
|
|
})
|
|
|
|
|
else:
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 无效类型重定向到首页
|
|
|
|
|
=======
|
|
|
|
|
# 操作类型不合法,重定向到首页
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
return HttpResponseRedirect('/')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 忘记密码视图,继承自FormView
|
|
|
|
|
class ForgetPasswordView(FormView):
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 使用的表单类
|
|
|
|
|
form_class = ForgetPasswordForm
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 模板文件路径
|
|
|
|
|
template_name = 'account/forget_password.html'
|
|
|
|
|
|
|
|
|
|
=======
|
|
|
|
|
"""
|
|
|
|
|
忘记密码类视图,继承自FormView
|
|
|
|
|
负责密码重置表单展示、数据验证,及更新用户密码
|
|
|
|
|
"""
|
|
|
|
|
form_class = ForgetPasswordForm # 指定使用的密码重置表单
|
|
|
|
|
template_name = 'account/forget_password.html' # 密码重置页面模板路径
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
=======
|
|
|
|
|
template_name = 'account/forget_password.html'#处理忘记密码逻辑,指定表单类ForgetPasswordForm和模板account/forget_password.html
|
|
|
|
|
>>>>>>> LXY_branch
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 表单验证通过后的处理
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
|
"""表单验证通过后执行的逻辑(密码重置核心流程)"""
|
|
|
|
|
if form.is_valid():
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 根据邮箱获取用户对象
|
|
|
|
|
blog_user = BlogUser.objects.filter(email=form.cleaned_data.get("email")).get()
|
|
|
|
|
# 设置新密码(加密)
|
|
|
|
|
=======
|
|
|
|
|
# 1. 获取表单中的邮箱,查询对应的用户
|
|
|
|
|
blog_user = BlogUser.objects.filter(
|
|
|
|
|
email=form.cleaned_data.get("email")
|
|
|
|
|
).get()
|
|
|
|
|
# 2. 对新密码进行哈希处理,并更新用户密码
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
blog_user.password = make_password(form.cleaned_data["new_password2"])
|
|
|
|
|
# 保存用户对象
|
|
|
|
|
blog_user.save()
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 重定向到登录页面
|
|
|
|
|
return HttpResponseRedirect('/login/')
|
|
|
|
|
else:
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 表单无效,重新渲染表单并显示错误
|
|
|
|
|
=======
|
|
|
|
|
# 3. 密码重置成功,重定向到登录页
|
|
|
|
|
return HttpResponseRedirect('/login/')
|
|
|
|
|
else:
|
|
|
|
|
# 表单验证失败(如验证码错误、密码不一致),重新渲染表单
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
return self.render_to_response({'form': form})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 忘记密码验证码发送视图,继承自View
|
|
|
|
|
class ForgetPasswordEmailCode(View):
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 处理POST请求
|
|
|
|
|
=======
|
|
|
|
|
return self.render_to_response({'form': form})#form_valid方法中验证表单后,重置用户密码并重定向到登录页
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ForgetPasswordEmailCode(View):# 处理忘记密码的邮箱验证码发送逻辑
|
|
|
|
|
|
|
|
|
|
>>>>>>> LXY_branch
|
|
|
|
|
def post(self, request: HttpRequest):
|
|
|
|
|
# 验证表单
|
|
|
|
|
form = ForgetPasswordCodeForm(request.POST)
|
|
|
|
|
if not form.is_valid():
|
|
|
|
|
# 表单无效返回错误
|
|
|
|
|
return HttpResponse("错误的邮箱")
|
|
|
|
|
# 获取邮箱地址
|
|
|
|
|
to_email = form.cleaned_data["email"]
|
|
|
|
|
|
|
|
|
|
# 生成验证码
|
|
|
|
|
code = generate_code()
|
|
|
|
|
# 发送验证邮件
|
|
|
|
|
utils.send_verify_email(to_email, code)
|
|
|
|
|
# 存储验证码(通常有有效期)
|
|
|
|
|
utils.set_code(to_email, code)
|
|
|
|
|
<<<<<<< HEAD
|
|
|
|
|
# 返回成功响应
|
|
|
|
|
return HttpResponse("ok")
|
|
|
|
|
=======
|
|
|
|
|
"""
|
|
|
|
|
发送密码重置验证码类视图,继承自基础View
|
|
|
|
|
负责验证邮箱合法性、生成验证码、发送验证邮件,并返回结果
|
|
|
|
|
"""
|
|
|
|
|
def post(self, request: HttpRequest):
|
|
|
|
|
"""处理POST请求(发送验证码核心逻辑)"""
|
|
|
|
|
# 1. 验证邮箱表单数据
|
|
|
|
|
form = ForgetPasswordCodeForm(request.POST)
|
|
|
|
|
if not form.is_valid():
|
|
|
|
|
return HttpResponse("错误的邮箱") # 邮箱格式不合法,返回错误提示
|
|
|
|
|
|
|
|
|
|
# 2. 生成验证码并发送邮件
|
|
|
|
|
to_email = form.cleaned_data["email"] # 获取合法的邮箱地址
|
|
|
|
|
code = generate_code() # 生成随机验证码
|
|
|
|
|
utils.send_verify_email(to_email, code) # 发送验证码邮件
|
|
|
|
|
utils.set_code(to_email, code) # 将验证码存入缓存(设置有效期)
|
|
|
|
|
|
|
|
|
|
# 3. 操作成功,返回“ok”提示
|
|
|
|
|
return HttpResponse("ok")
|
|
|
|
|
>>>>>>> JYN_branch
|
|
|
|
|
=======
|
|
|
|
|
|
|
|
|
|
return HttpResponse("ok")# post方法中验证邮箱表单,生成并发送验证码,将验证码存入缓存后返回成功标识
|
|
|
|
|
>>>>>>> LXY_branch
|
|
|
|
|
|