h|JA(4Ujv5)2~K2>Hm<%o{2
z;(EfseeFDia2d8wsEweux0Xy?OMbA6Fm2dH;Y}o5LP0lh93_4n2}Z#4NU-OFTsZzK
z24nyjcLfNfqK`JOw)D|Wee`?b-uMs6`==k!ZT++53+?pSt*KUeY%@K!df> VrQ~pd-Wa~R`_r%f^x4z 请点击下面链接验证您的邮箱lJ0qIB2GY
z(hf>DQN|Ug2w|EKgobd#6~UuYaf7@wKly+6q%TUnAjsnttU$}LGRAShKrYD!w4JRgb=Jr0)5?wZ`??lzs-
zGfBBZEm6`3HApr3mIo0f66%wJl+rgrkc5aimlgz@#=b>Qq2$T$+uM_)p8eSU&2M(T
z`DW((ezQOH_4N?2A3ywgHX{-88+O{JgrxaAkTqfxo0dt1<|#$a%B&*gB}y21mDtiU
zv1LcvfEZ|bc}dYD50UEB@1Jozqb3|~R9xFB!q%828we<1vj)QU?qj7zQuN1wVR8
zxOz|mv3ynNH4KAvMX!Fr=_2fHkW9K*zpf!LDu%((z;qCd!`;v%Z8#`Sy$2X>Ac_Su
za2ZzPGG0p;`7%_iE|T&ffJ}au@!AP;2-SS3{W!&M)nnA33W}1Tv3JUw@N83dHtHYX
z4guZM@3m;+oU$e#G|~8zZtH363DJ6>Bz^GISYI|s80zIC5Wxi`3rj9Z7o|ku`dH!m
zMB&C*;l_#PM15
+ 如果上面链接无法打开,请将此链接复制至浏览器。
+ {url}
+ """.format(url=url)
+ # 发送验证邮件
+ send_email(
+ emailto=[user.email],
+ title='验证您的电子邮箱',
+ content=content)
+
+ # 重定向到结果页面
+ url = reverse('accounts:result') + '?type=register&id=' + str(user.id)
+ return HttpResponseRedirect(url)
+ else:
+ # 表单无效,重新渲染表单页
+ return self.render_to_response({'form': form})
+
+
+class LogoutView(RedirectView):
+ """用户登出视图"""
+ url = '/login/' # 登出后重定向的URL
+
+ @method_decorator(never_cache) # 禁止缓存装饰器
+ def dispatch(self, request, *args, **kwargs):
+ """请求分发方法"""
+ return super(LogoutView, self).dispatch(request, *args, **kwargs)
+
+ def get(self, request, *args, **kwargs):
+ """处理GET请求"""
+ logout(request) # 执行登出操作
+ delete_sidebar_cache() # 删除侧边栏缓存
+ return super(LogoutView, self).get(request, *args, **kwargs)
+
+
+class LoginView(FormView):
+ """用户登录视图"""
+ form_class = LoginForm # 使用自定义登录表单
+ template_name = 'account/login.html' # 登录模板路径
+ success_url = '/' # 登录成功默认重定向URL
+ redirect_field_name = REDIRECT_FIELD_NAME # 重定向字段名
+ login_ttl = 2626560 # 会话有效期:一个月(以秒为单位)
+
+ # 方法装饰器:保护敏感数据、CSRF防护、禁止缓存
+ @method_decorator(sensitive_post_parameters('password'))
+ @method_decorator(csrf_protect)
+ @method_decorator(never_cache)
+ def dispatch(self, request, *args, **kwargs):
+ """请求分发方法"""
+ return super(LoginView, self).dispatch(request, *args, **kwargs)
+
+ def get_context_data(self, **kwargs):
+ """获取模板上下文数据"""
+ # 获取重定向URL
+ redirect_to = self.request.GET.get(self.redirect_field_name)
+ if redirect_to is None:
+ redirect_to = '/' # 默认重定向到首页
+ kwargs['redirect_to'] = redirect_to
+
+ return super(LoginView, self).get_context_data(**kwargs)
+
+ def form_valid(self, form):
+ """表单验证通过后的处理"""
+ # 使用Django内置的认证表单
+ form = AuthenticationForm(data=self.request.POST, request=self.request)
+
+ if form.is_valid():
+ # 清除侧边栏缓存
+ delete_sidebar_cache()
+ logger.info(self.redirect_field_name)
+
+ # 执行登录操作
+ auth.login(self.request, form.get_user())
+
+ # 处理"记住我"功能
+ if self.request.POST.get("remember"):
+ self.request.session.set_expiry(self.login_ttl) # 设置会话有效期
+
+ return super(LoginView, self).form_valid(form)
+ else:
+ # 表单无效,重新渲染表单页
+ return self.render_to_response({'form': form})
+
+ def get_success_url(self):
+ """获取登录成功后的重定向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()]):
+ redirect_to = self.success_url # 不安全的URL使用默认URL
+ return redirect_to
+
+
+def account_result(request):
+ """账户操作结果页面视图函数"""
+ type = request.GET.get('type') # 操作类型
+ id = request.GET.get('id') # 用户ID
+
+ # 获取用户对象,不存在则返回404
+ user = get_object_or_404(get_user_model(), id=id)
+ logger.info(type)
+
+ # 如果用户已激活,重定向到首页
+ if user.is_active:
+ return HttpResponseRedirect('/')
+
+ # 处理注册和验证两种类型
+ if type and type in ['register', 'validation']:
+ if type == 'register':
+ # 注册成功页面内容
+ content = '''
+ 恭喜您注册成功,一封验证邮件已经发送到您的邮箱,请验证您的邮箱后登录本站。
+ '''
+ title = '注册成功'
+ else:
+ # 邮箱验证处理
+ c_sign = get_sha256(get_sha256(settings.SECRET_KEY + str(user.id)))
+ sign = request.GET.get('sign')
+ # 验证签名
+ if sign != c_sign:
+ return HttpResponseForbidden() # 签名不匹配,拒绝访问
+ # 激活用户
+ user.is_active = True
+ user.save()
+ content = '''
+ 恭喜您已经成功的完成邮箱验证,您现在可以使用您的账号来登录本站。
+ '''
+ title = '验证成功'
+ # 渲染结果页面
+ return render(request, 'account/result.html', {
+ 'title': title,
+ 'content': content
+ })
+ else:
+ # 无效类型,重定向到首页
+ return HttpResponseRedirect('/')
+
+
+class ForgetPasswordView(FormView):
+ """忘记密码重置视图"""
+ form_class = ForgetPasswordForm # 使用忘记密码表单
+ template_name = 'account/forget_password.html' # 模板路径
+
+ def form_valid(self, form):
+ """表单验证通过后的处理"""
+ if form.is_valid():
+ # 获取用户并重置密码
+ blog_user = BlogUser.objects.filter(email=form.cleaned_data.get("email")).get()
+ # 对密码进行哈希处理
+ blog_user.password = make_password(form.cleaned_data["new_password2"])
+ blog_user.save() # 保存用户
+ return HttpResponseRedirect('/login/') # 重定向到登录页
+ else:
+ # 表单无效,重新渲染表单页
+ return self.render_to_response({'form': form})
+
+
+class ForgetPasswordEmailCode(View):
+ """忘记密码验证码发送视图"""
+
+ def post(self, request: HttpRequest):
+ """处理POST请求,发送验证码"""
+ 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)
+
+ return HttpResponse("ok") # 返回成功响应
\ No newline at end of file