Skip to content

Commit aa09193

Browse files
committed
feat:新增忘记密码模块(模拟短信验证码)
fix:修复bug
1 parent 62d9cd8 commit aa09193

File tree

13 files changed

+252
-323
lines changed

13 files changed

+252
-323
lines changed

dash-fastapi-backend/module_admin/controller/login_controller.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import uuid
21
from fastapi import APIRouter
32
from module_admin.service.login_service import *
43
from module_admin.entity.vo.login_vo import *
@@ -65,6 +64,36 @@ async def login(request: Request, form_data: CustomOAuth2PasswordRequestForm = D
6564
return response_500(data="", message=str(e))
6665

6766

67+
@loginController.post("/getSmsCode", response_model=SmsCode)
68+
async def get_sms_code(request: Request, user: ResetUserModel, query_db: Session = Depends(get_db)):
69+
try:
70+
sms_result = await get_sms_code_services(request, query_db, user)
71+
if sms_result.is_success:
72+
logger.info('获取成功')
73+
return response_200(data=sms_result, message='获取成功')
74+
else:
75+
logger.warning(sms_result.message)
76+
return response_400(data='', message=sms_result.message)
77+
except Exception as e:
78+
logger.exception(e)
79+
return response_500(data="", message=str(e))
80+
81+
82+
@loginController.post("/forgetPwd", response_model=CrudUserResponse)
83+
async def forget_user_pwd(request: Request, forget_user: ResetUserModel, query_db: Session = Depends(get_db)):
84+
try:
85+
forget_user_result = await forget_user_services(request, query_db, forget_user)
86+
if forget_user_result.is_success:
87+
logger.info(forget_user_result.message)
88+
return response_200(data=forget_user_result, message=forget_user_result.message)
89+
else:
90+
logger.warning(forget_user_result.message)
91+
return response_400(data="", message=forget_user_result.message)
92+
except Exception as e:
93+
logger.exception(e)
94+
return response_500(data="", message=str(e))
95+
96+
6897
@loginController.post("/getLoginUserInfo", response_model=CurrentUserInfoServiceResponse, dependencies=[Depends(CheckUserInterfaceAuth('common'))])
6998
async def get_login_user_info(request: Request, current_user: CurrentUserInfoServiceResponse = Depends(get_current_user)):
7099
try:

dash-fastapi-backend/module_admin/controller/user_controller.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import base64
44
from config.get_db import get_db
55
from config.env import CachePathConfig
6-
from module_admin.service.login_service import get_current_user, get_password_hash
6+
from module_admin.service.login_service import get_current_user
77
from module_admin.service.user_service import *
88
from module_admin.entity.vo.user_vo import *
99
from module_admin.dao.user_dao import *
@@ -37,7 +37,7 @@ async def get_system_user_list(request: Request, user_page_query: UserPageObject
3737
@log_decorator(title='用户管理', business_type=1)
3838
async def add_system_user(request: Request, add_user: AddUserModel, query_db: Session = Depends(get_db), current_user: CurrentUserInfoServiceResponse = Depends(get_current_user)):
3939
try:
40-
add_user.password = get_password_hash(add_user.password)
40+
add_user.password = PwdUtil.get_password_hash(add_user.password)
4141
add_user.create_by = current_user.user.user_name
4242
add_user.update_by = current_user.user.user_name
4343
add_user_result = UserService.add_user_services(query_db, add_user)
@@ -155,9 +155,9 @@ async def change_system_user_profile_info(request: Request, edit_user: AddUserMo
155155
@log_decorator(title='个人信息', business_type=2)
156156
async def reset_system_user_password(request: Request, reset_user: ResetUserModel, query_db: Session = Depends(get_db), current_user: CurrentUserInfoServiceResponse = Depends(get_current_user)):
157157
try:
158-
if not reset_user.user_id:
158+
if not reset_user.user_id and reset_user.old_password:
159159
reset_user.user_id = current_user.user.user_id
160-
reset_user.password = get_password_hash(reset_user.password)
160+
reset_user.password = PwdUtil.get_password_hash(reset_user.password)
161161
reset_user.update_by = current_user.user.user_name
162162
reset_user.update_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
163163
reset_user_result = UserService.reset_user_services(query_db, reset_user)

dash-fastapi-backend/module_admin/entity/vo/login_vo.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,10 @@ class UserLogin(BaseModel):
1414
class Token(BaseModel):
1515
access_token: str
1616
token_type: str
17+
18+
19+
class SmsCode(BaseModel):
20+
is_success: Optional[bool]
21+
sms_code: str
22+
session_id: str
23+
message: Optional[str]

dash-fastapi-backend/module_admin/entity/vo/user_vo.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ class ResetUserModel(UserModel):
200200
重置用户密码模型
201201
"""
202202
old_password: Optional[str]
203+
sms_code: Optional[str]
204+
session_id: Optional[str]
203205

204206

205207
class DeleteUserModel(BaseModel):

dash-fastapi-backend/module_admin/service/login_service.py

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
from module_admin.entity.vo.user_vo import *
2-
from module_admin.entity.vo.login_vo import UserLogin
2+
from module_admin.entity.vo.login_vo import *
33
from module_admin.dao.login_dao import *
4+
from module_admin.service.user_service import UserService
45
from module_admin.dao.user_dao import *
56
from jose import JWTError, jwt
6-
from passlib.context import CryptContext
77
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
8+
import random
9+
import uuid
810
from config.env import JwtConfig
11+
from utils.pwd_util import *
912
from utils.response_util import *
1013
from utils.log_util import *
14+
from utils.message_util import *
1115
from datetime import datetime, timedelta
1216
from fastapi import Request, Form
1317
from fastapi import Depends, Header
1418
from config.get_db import get_db
1519

16-
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
1720
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login/loginByAccount")
1821

1922

@@ -94,37 +97,65 @@ async def get_current_user(request: Request = Request, token: str = Depends(oaut
9497
raise AuthException(data="", message="用户token已失效,请重新登录")
9598

9699

97-
async def logout_services(request: Request, session_id: str):
100+
async def get_sms_code_services(request: Request, result_db: Session, user: ResetUserModel):
98101
"""
99-
退出登录services
102+
获取短信验证码service
100103
:param request: Request对象
101-
:param session_id: 会话编号
102-
:return: 退出登录结果
104+
:param result_db: orm对象
105+
:param user: 用户对象
106+
:return: 短信验证码对象
103107
"""
104-
await request.app.state.redis.delete(f'access_token:{session_id}')
105-
# await request.app.state.redis.delete(f'{current_user.user.user_id}_access_token')
106-
# await request.app.state.redis.delete(f'{current_user.user.user_id}_session_id')
108+
redis_sms_result = await request.app.state.redis.get(f"sms_code:{user.session_id}")
109+
if redis_sms_result:
110+
return SmsCode(**dict(is_success=False, sms_code='', session_id='', message='短信验证码仍在有效期内'))
111+
is_user = UserDao.get_user_by_name(result_db, user.user_name)
112+
if is_user:
113+
sms_code = str(random.randint(100000, 999999))
114+
session_id = str(uuid.uuid4())
115+
await request.app.state.redis.set(f"sms_code:{session_id}", sms_code, ex=timedelta(minutes=2))
116+
# 此处模拟调用短信服务
117+
message_service(sms_code)
107118

108-
return True
119+
return SmsCode(**dict(is_success=True, sms_code=sms_code, session_id=session_id, message='获取成功'))
120+
121+
return SmsCode(**dict(is_success=False, sms_code='', session_id='', message='用户不存在'))
109122

110123

111-
def verify_password(plain_password, hashed_password):
124+
async def forget_user_services(request: Request, result_db: Session, forget_user: ResetUserModel):
112125
"""
113-
工具方法:校验当前输入的密码与数据库存储的密码是否一致
114-
:param plain_password: 当前输入的密码
115-
:param hashed_password: 数据库存储的密码
116-
:return: 校验结果
126+
用户忘记密码services
127+
:param request: Request对象
128+
:param result_db: orm对象
129+
:param forget_user: 重置用户对象
130+
:return: 重置结果
117131
"""
118-
return pwd_context.verify(plain_password, hashed_password)
132+
redis_sms_result = await request.app.state.redis.get(f"sms_code:{forget_user.session_id}")
133+
if forget_user.sms_code == redis_sms_result:
134+
forget_user.password = PwdUtil.get_password_hash(forget_user.password)
135+
forget_user.user_id = UserDao.get_user_by_name(result_db, forget_user.user_name).user_id
136+
edit_result = UserService.reset_user_services(result_db, forget_user)
137+
result = edit_result.dict()
138+
elif not redis_sms_result:
139+
result = dict(is_success=False, message='短信验证码已过期')
140+
else:
141+
await request.app.state.redis.delete(f"sms_code:{forget_user.session_id}")
142+
result = dict(is_success=False, message='短信验证码不正确')
143+
144+
return CrudUserResponse(**result)
119145

120146

121-
def get_password_hash(input_password):
147+
async def logout_services(request: Request, session_id: str):
122148
"""
123-
工具方法:对当前输入的密码进行加密
124-
:param input_password: 输入的密码
125-
:return: 加密成功的密码
149+
退出登录services
150+
:param request: Request对象
151+
:param session_id: 会话编号
152+
:return: 退出登录结果
126153
"""
127-
return pwd_context.hash(input_password)
154+
await request.app.state.redis.delete(f'access_token:{session_id}')
155+
# await request.app.state.redis.delete(f'{current_user.user.user_id}_access_token')
156+
# await request.app.state.redis.delete(f'{current_user.user.user_id}_session_id')
157+
158+
return True
128159

129160

130161
async def check_login_captcha(request: Request, login_user: UserLogin):
@@ -160,10 +191,10 @@ async def authenticate_user(request: Request, query_db: Session, login_user: Use
160191
if login_user.captcha_enabled:
161192
await check_login_captcha(request, login_user)
162193
user = login_by_account(query_db, login_user.user_name)
163-
if not user[0]:
194+
if not user:
164195
logger.warning("用户不存在")
165196
raise LoginException(data="", message="用户不存在")
166-
if not verify_password(login_user.password, user[0].password):
197+
if not PwdUtil.verify_password(login_user.password, user[0].password):
167198
cache_password_error_count = await request.app.state.redis.get(f"password_error_count:{login_user.user_name}")
168199
password_error_counted = 0
169200
if cache_password_error_count:

dash-fastapi-backend/module_admin/service/user_service.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
from fastapi import Request
12
from module_admin.entity.vo.user_vo import *
23
from module_admin.dao.user_dao import *
3-
from module_admin.service.login_service import verify_password
4+
from utils.pwd_util import *
45
from utils.common_util import export_list2excel
56

67

@@ -152,19 +153,26 @@ def reset_user_services(cls, result_db: Session, page_object: ResetUserModel):
152153
:param page_object: 重置用户对象
153154
:return: 重置用户校验结果
154155
"""
155-
user = UserDao.get_user_detail_by_id(result_db, user_id=page_object.user_id).user_basic_info[0]
156+
reset_user = page_object.dict(exclude_unset=True)
156157
if page_object.old_password:
157-
if not verify_password(page_object.old_password, user.password):
158-
result = CrudUserResponse(**dict(is_success=False, message='旧密码不正确'))
158+
user = UserDao.get_user_detail_by_id(result_db, user_id=page_object.user_id).user_basic_info[0]
159+
if not PwdUtil.verify_password(page_object.old_password, user.password):
160+
result = dict(is_success=False, message='旧密码不正确')
161+
return CrudUserResponse(**result)
159162
else:
160-
reset_user = page_object.dict(exclude_unset=True)
161163
del reset_user['old_password']
162-
result = UserDao.edit_user_dao(result_db, reset_user)
163-
else:
164-
reset_user = page_object.dict(exclude_unset=True)
165-
result = UserDao.edit_user_dao(result_db, reset_user)
164+
if page_object.sms_code and page_object.session_id:
165+
del reset_user['sms_code']
166+
del reset_user['session_id']
167+
try:
168+
UserDao.edit_user_dao(result_db, reset_user)
169+
result_db.commit()
170+
result = dict(is_success=True, message='重置成功')
171+
except Exception as e:
172+
result_db.rollback()
173+
result = dict(is_success=False, message=str(e))
166174

167-
return result
175+
return CrudUserResponse(**result)
168176

169177
@staticmethod
170178
def export_user_list_services(user_list: List):
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from utils.log_util import logger
2+
3+
4+
def message_service(sms_code: str):
5+
logger.info(f"短信验证码为{sms_code}")
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from passlib.context import CryptContext
2+
3+
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
4+
5+
6+
class PwdUtil:
7+
"""
8+
密码工具类
9+
"""
10+
11+
@classmethod
12+
def verify_password(cls, plain_password, hashed_password):
13+
"""
14+
工具方法:校验当前输入的密码与数据库存储的密码是否一致
15+
:param plain_password: 当前输入的密码
16+
:param hashed_password: 数据库存储的密码
17+
:return: 校验结果
18+
"""
19+
return pwd_context.verify(plain_password, hashed_password)
20+
21+
@classmethod
22+
def get_password_hash(cls, input_password):
23+
"""
24+
工具方法:对当前输入的密码进行加密
25+
:param input_password: 输入的密码
26+
:return: 加密成功的密码
27+
"""
28+
return pwd_context.hash(input_password)

dash-fastapi-frontend/api/message.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33

44
def send_message_api(page_obj: dict):
55

6-
return api_request(method='post', url='/login/loginByAccount', is_headers=False, json=page_obj)
6+
return api_request(method='post', url='/login/getSmsCode', is_headers=False, json=page_obj)

dash-fastapi-frontend/api/user.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from utils.request import api_request
22

33

4-
def change_password_api(page_obj: dict):
4+
def forget_user_pwd_api(page_obj: dict):
55

6-
return api_request(method='post', url='/login/loginByAccount', is_headers=False, json=page_obj)
6+
return api_request(method='post', url='/login/forgetPwd', is_headers=False, json=page_obj)
77

88

99
def get_user_list_api(page_obj: dict):

0 commit comments

Comments
 (0)