You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DjangoBlog/accounts/utils.py

79 lines
4.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import typing
from datetime import timedelta
from django.core.cache import cache # Django缓存框架用于存储验证码内存/Redis等由项目配置决定
from django.utils.translation import gettext
from django.utils.translation import gettext_lazy as _ # 国际化支持,用于生成多语言提示文本
from djangoblog.utils import send_email # 导入项目公共邮件发送工具函数
_code_ttl = timedelta(minutes=5) # 验证码有效期5分钟全局常量统一控制验证码过期时间
def send_verify_email(to_mail: str, code: str, subject: str = _("Verify Email")):
"""
发送密码重置验证邮件(核心功能:向目标邮箱发送含验证码的邮件)
邮件内容支持国际化,验证码有效期与全局常量`_code_ttl`保持一致5分钟
Args:
to_mail: 接收邮件的目标邮箱地址(字符串类型,需符合邮箱格式)
code: 生成的随机验证码(字符串类型,用于后续密码重置验证)
subject: 邮件主题(可选参数,默认值为国际化的"Verify Email",支持多语言切换)
"""
# 构建邮件HTML内容国际化模板通过占位符注入验证码明确告知有效期
html_content = _(
"You are resetting the password, the verification code is%(code)s, valid within 5 minutes, please keep it "
"properly") % {'code': code}
# 调用项目公共邮件发送函数发送验证码邮件收件人列表、主题、HTML内容
send_email([to_mail], subject, html_content)
def verify(email: str, code: str) -> typing.Optional[str]:
"""
验证验证码的有效性(核心功能:校验用户输入的验证码与缓存中存储的是否一致)
Args:
email: 待验证的邮箱地址(与验证码绑定的唯一标识,确保验证码针对性)
code: 用户输入的验证码(需与缓存中存储的验证码比对)
Return:
验证失败返回错误提示字符串支持国际化验证成功返回None
Note:
1. 原代码注释保留当前错误处理逻辑不合理建议改用raise抛出异常而非返回错误字符串
便于调用方统一捕获和处理,减少错误处理冗余;
2. 验证码校验逻辑通过邮箱作为缓存key获取存储的验证码与输入值直接比对大小写敏感
3. 若缓存中无该邮箱对应的验证码(如过期、未发送),则默认返回验证码错误提示。
"""
# 从缓存中获取该邮箱对应的验证码缓存key为邮箱地址value为之前存储的验证码
cache_code = get_code(email)
# 比对缓存中的验证码与用户输入的验证码,不一致则返回错误提示
if cache_code != code:
return gettext("Verification code error") # 国际化的验证码错误提示
def set_code(email: str, code: str):
"""
将邮箱与验证码绑定并存储到缓存中(核心功能:为后续验证提供数据支持)
存储时自动设置过期时间(与全局`_code_ttl`一致5分钟避免验证码永久有效
Args:
email: 验证码绑定的邮箱地址作为缓存的唯一key确保一对一关联
code: 需存储的随机验证码(字符串类型,建议由`generate_code`等工具函数生成)
"""
# 缓存存储key=邮箱地址value=验证码timeout=有效期秒数由_timedelta转换
cache.set(email, code, _code_ttl.seconds)
def get_code(email: str) -> typing.Optional[str]:
"""
从缓存中获取指定邮箱对应的验证码(核心功能:为验证码校验提供数据源)
Args:
email: 目标邮箱地址缓存key用于精准获取绑定的验证码
Return:
缓存中存在该邮箱对应的验证码则返回字符串类型的验证码否则返回None如过期、未存储
"""
# 从缓存中获取值key为邮箱地址不存在或过期时返回None
return cache.get(email)