bifangback-又一个典型的用户模块功能实现
2021-01-04 本文已影响0人
万州客
为了能在一个机器上跑起来服务。所以用户模块的找回密码功能,不用redis,直接用内存cache。验证码发邮箱,也不用真的邮箱,而使用console输出。
一,注释掉settings里的缓存和邮箱设置
# 自定义obtain_jwt_token登录参数验证
AUTHENTICATION_BACKENDS = (
'account.jwt_views.CustomJwtBackend',
)
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=365),
'JWT_AUTH_HEADER_PREFIX': 'Bearer',
'JWT_ALLOW_REFRESH': True,
}
# Django的redis缓存配置,性能要求高和有持久化要求时,可开启
# CACHES = {
# "default": {
# "BACKEND": "django_redis.cache.RedisCache",
# "LOCATION": "redis://127.0.0.1:6379/1",
# "OPTIONS": {
# "CLIENT_CLASS": "django_redis.client.DefaultClient",
# }
# }
# }
# 邮件发送到控制台,而不发送到实际的邮箱
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# 正式使用时的邮箱设置
# EMAIL_USE_SSL = True
# EMAIL_HOST = 'smtp.163.com'
# EMAIL_PORT = 465
# EMAIL_HOST_USER = 'aguncn@163.com'
# EMAIL_HOST_PASSWORD = 'xxxxxxx'
# DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
SIMPLE_HISTORY_REVERT_DISABLED = True
二,DRF的APIVIEW打天下,实现用户模块功能
from random import Random
from django.contrib.auth.hashers import check_password
from django.core.mail import send_mail
from rest_framework.views import APIView
from django.core.cache import cache
from django.contrib.auth import get_user_model
from utils.ret_code import *
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
User = get_user_model()
DEFAULT_FROM_EMAIL = 'aguncn@163.com'
def random_str(random_length=8):
code_str = ''
chars = 'abcdefghijklmnopqrstuvwsyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
length = len(chars) - 1
random = Random()
for i in range(random_length):
code_str += chars[random.randint(0, length)]
return code_str
# 用户注册
class UserRegisterView(APIView):
"""
用户注册
参数:
username
password
passwordConfirm
email
"""
authentication_classes = []
permission_classes = []
@swagger_auto_schema(
tags=['Users']
)
def post(self, request, *args, **kwargs):
req_data = request.data
username = req_data['username']
password = req_data['password']
password_confirm = req_data['passwordConfirm']
email = req_data['email']
if password != password_confirm:
return_dict = build_ret_data(THROW_EXP, '两次输入密码不一致!')
return render_json(return_dict)
if User.objects.filter(username=username):
return_dict = build_ret_data(THROW_EXP, '用户已经存在,请重新选择用户名!')
return render_json(return_dict)
try:
User.objects.create_user(username=username,
password=password,
email=email,
is_active=True)
return_dict = build_ret_data(OP_SUCCESS, str(req_data))
return render_json(return_dict)
except Exception as e:
print(e)
return_dict = build_ret_data(THROW_EXP, str(e))
return render_json(return_dict)
# 更新密码
class UpdatePasswordView(APIView):
"""
更改密码
参数:
username
currentPassword
newPassword
newPasswordConfirm
"""
@swagger_auto_schema(
tags=['Users']
)
def post(self, request, *args, **kwargs):
req_data = request.data
username = req_data['username']
login_username = request.user.username
if login_username != username:
return_dict = build_ret_data(THROW_EXP, '不能更新其它用户密码!')
return render_json(return_dict)
current_password = req_data['currentPassword']
user = User.objects.get(username=username)
if not check_password(current_password, user.password):
return_dict = build_ret_data(THROW_EXP, '当前密码错误,无法更新密码!')
return render_json(return_dict)
if login_username != username:
return_dict = build_ret_data(THROW_EXP, '两次输入密码不一致!')
return render_json(return_dict)
new_password_confirm = req_data['newPasswordConfirm']
new_password = req_data['newPassword']
if new_password != new_password_confirm:
return_dict = build_ret_data(THROW_EXP, '两次输入密码不一致!')
return render_json(return_dict)
try:
user.set_password(new_password)
user.save()
return_dict = build_ret_data(OP_SUCCESS, str(user))
return render_json(return_dict)
except Exception as e:
print(e)
return_dict = build_ret_data(THROW_EXP, str(e))
return render_json(return_dict)
# 更新邮箱
class UpdateEmailView(APIView):
"""
更改邮箱
参数:
username
newEmail
newEmailConfirm
"""
@swagger_auto_schema(
tags=['Users']
)
def post(self, request, *args, **kwargs):
req_data = request.data
username = req_data['username']
login_username = request.user.username
if login_username != username:
return_dict = build_ret_data(THROW_EXP, '不能更新其它用户密码!')
return render_json(return_dict)
user = User.objects.get(username=username)
new_email_confirm = req_data['newEmailConfirm']
new_email = req_data['newEmail']
if new_email != new_email_confirm:
return_dict = build_ret_data(THROW_EXP, '两次输入新邮箱地址不一致!')
return render_json(return_dict)
try:
user.email = new_email
user.save()
return_dict = build_ret_data(OP_SUCCESS, str(user))
return render_json(return_dict)
except Exception as e:
print(e)
return_dict = build_ret_data(THROW_EXP, str(e))
return render_json(return_dict)
# 发送验证码到邮箱
class ForgetPasswordView(APIView):
"""
发送验证码到邮箱
参数:
email
"""
authentication_classes = []
permission_classes = []
# swagger_schema = None # 可隐藏此API的swagger文档
@swagger_auto_schema(
manual_parameters=[
openapi.Parameter('email', openapi.IN_QUERY, "test manual param", type=openapi.TYPE_STRING),
],
responses={
200: openapi.Response('response description', None),
},
tags=['Users']
)
def post(self, request, *args, **kwargs):
req_data = request.data
email_title = "找回密码"
random_code = random_str()
email_body = "验证码为:{0}".format(random_code)
email = req_data['email']
if not User.objects.get(email=email):
return_dict = build_ret_data(THROW_EXP, '此邮件不存在')
return render_json(return_dict)
# conn = get_redis_connection('default')
# conn.set(email, random_code, ex=5)
cache.set(email, random_code)
email_to = [email]
try:
send_status = send_mail(email_title, email_body, DEFAULT_FROM_EMAIL, email_to, )
return_dict = build_ret_data(OP_SUCCESS, str(send_status))
return render_json(return_dict)
except Exception as e:
print(e)
return_dict = build_ret_data(THROW_EXP, str(e))
return render_json(return_dict)
# 发送新密码到邮箱
class ResetPasswordView(APIView):
"""
发送新密码到邮箱
参数:
email
verificationCode
"""
authentication_classes = []
permission_classes = []
@swagger_auto_schema(
tags=['Users']
)
def post(self, request, *args, **kwargs):
req_data = request.data
email = req_data['email']
verification_code = req_data['verificationCode']
email_title = "新密码,请妥善保存"
new_password = random_str()
email_body = "新密码为:{0}".format(new_password)
user = User.objects.get(email=email)
if not user:
return_dict = build_ret_data(THROW_EXP, '此邮件不存在')
return render_json(return_dict)
email_to = [email]
redis_verification_code = cache.get(email)
print(verification_code, redis_verification_code)
if verification_code != redis_verification_code:
return_dict = build_ret_data(THROW_EXP, '验证码错误')
return render_json(return_dict)
try:
user.set_password(new_password)
user.save()
send_status = send_mail(email_title, email_body, DEFAULT_FROM_EMAIL, email_to, )
return_dict = build_ret_data(OP_SUCCESS, str(send_status))
return render_json(return_dict)
except Exception as e:
print(e)
return_dict = build_ret_data(THROW_EXP, str(e))
return render_json(return_dict)
三,Postman测试
1,用户注册
网址:http://localhost:8000/account/register/
参数:
{
"username": "sky",
"password": "password",
"passwordConfirm": "password",
"email": "adbc@ad.com"
}
正确返回
{
"code": 0,
"message": "操作成功",
"data": "{'username': 'sky', 'password': 'password', 'passwordConfirm': 'password', 'email': 'adbc@ad.com'}"
}
错误返回
{
"code": 1000,
"message": "抛出异常",
"data": "用户已经存在,请重新选择用户名!"
}
2,其它的功能。
http://localhost:8000/account/register/
{
"username": "sky",
"password": "password",
"passwordConfirm": "password",
"email": "adbc@ad.com"
}
{
"code": 0,
"message": "操作成功",
"data": "{'username': 'sky', 'password': 'password', 'passwordConfirm': 'password', 'email': 'adbc@ad.com'}"
}
{
"code": 1000,
"message": "抛出异常",
"data": "用户已经存在,请重新选择用户名!"
}
http://localhost:8000/account/update_password/
{
"username": "admin",
"currentPassword": "password",
"newPassword": "password2",
"newPasswordConfirm": "password2"
}
{
"code": 0,
"message": "操作成功",
"data": "admin"
}
{
"code": 1000,
"message": "抛出异常",
"data": "当前密码错误,无法更新密码!"
}
http://localhost:8000/account/update_email/
{
"username": "admin",
"newEmailConfirm": "admin@demo.com",
"newEmail": "admin@demo.com"
}
{
"code": 0,
"message": "操作成功",
"data": "admin"
}
http://localhost:8000/account/forget_password/
{
"email": "admin@demo.com"
}
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Subject: =?utf-8?b?5om+5Zue5a+G56CB?=
From: aguncn@163.com
To: admin@demo.com
Date: Sun, 03 Jan 2021 13:39:37 -0000
Message-ID: <160968117789.1732.12157315585525517403@LAPTOP-4H048BJN>
验证码为:d3svKRGK
-------------------------------------------------------------------------------
[03/Jan/2021 21:39:40] "POST /account/forget_password/ HTTP/1.1" 200 63
http://localhost:8000/account/reset_password/
{
"email": "admin@demo.com",
"verificationCode": "d3svKRGK"
}
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Subject: =?utf-8?b?5paw5a+G56CB77yM6K+35aal5ZaE5L+d5a2Y?=
From: aguncn@163.com
To: admin@demo.com
Date: Sun, 03 Jan 2021 13:42:27 -0000
Message-ID: <160968134723.1732.17373769924101658415@LAPTOP-4H048BJN>
新密码为:pEd3a7wu
-------------------------------------------------------------------------------
[03/Jan/2021 21:42:27] "POST /account/reset_password/ HTTP/1.1" 200 63
累了,一锅端,慢慢看。
2021-01-03 21_44_29-悬浮球.png 2021-01-03 21_40_06-C__Windows_system32_cmd.exe - python manage.py runserver.png 2021-01-03 21_32_16-悬浮球.png