今天主要是唠嗑下登录接口的两个bug,哈哈……真实印证了一句话,一行代码除了十个bug。
- 密码错误也登录成功了
- 针对不存在的账号进行查询时没有严谨处理,导致查询时会报错500
首先,看下代码出错的地方:
def check_user(user: str, pwd: str, db: Session = Depends(get_db)): """ 根据输入的用户信息,数据库查询比对账号和密码,并对密码进行解密操作 :param user: :param pwd: :param db: :return: """ username, password = db.query( user_models.Users.username, user_models.Users.password ).filter(user_models.Users.username == user).first() if not username and not encryption_password_or_decode(pwd=pwd, hashed_password=password): return False return True
check_user函数主要是验证数据查询登录账号,然后进行密码比对是否相等。
问题1- 出错代码:
if not username and not encryption_password_or_decode(pwd=pwd, hashed_password=password): return False return True
因为encryption_password_or_decode这个函数是专门验证密码是否相等,如果相等就返回True,否则就是False,然后因为多加了一个not,所以这个if条件就不成立了,那就直接返回True
而登录接口中又有一个非真判断,因为一直是True所以这个判断也失效了
# 如果返回False则抛出错误 if not check_user(user.username, user.password, db):
这种情况就会出现密码错误,也可以登录的情况,这也是在写代码的不细心导致的,测试也没站在测试的角度进行测试。
问题2- 出错代码:
username, password = db.query( user_models.Users.username, user_models.Users.password ).filter(user_models.Users.username == user).first()
这一段是查询语句,主要是根据账号查询账号和密码。但是这里只考虑了有username, password的情况,忽略了可能为None的情况,运行时控制台就会抛出错误信息:TypeError: cannot unpack non-iterable NoneType object
主要原因就是因为没查询到数据,返回的是一个None值,而用了两个变量去接收,故而抛出错误信息
这个问题是考虑不严谨导致的,也是细心问题,测试也没站在测试的角度进行测试。
问题代码找到以后,就开始进行代码修改,因为两个错误都在一段代码中,修改代码如下:
exception_catch = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail={
"status": 0,
"data": {},
"error_msg": "账号或密码不正确 !",
"error_code": 1000
}
)
def check_user(user: str, pwd: str, db: Session = Depends(get_db)):
"""
根据输入的用户信息,数据库查询比对账号和密码,并对密码进行解密操作
:param user:
:param pwd:
:param db:
:return:
"""
user_info = db.query(
user_models.Users.username, user_models.Users.password
).filter(user_models.Users.username == user).first()
if user_info:
username, password = user_info
return True if username and encryption_password_or_decode(pwd=pwd, hashed_password=password) else False
else:
raise exception_catch
登录接口中的代码无须作任何修改,因为主要原因都在check_user函数中,唯一作了修改的就是和check_user函数共用了一个异常抛出
@router.post("/login/", response_model=UserToken, summary="登录接口", description="主要用于用户登录,并生成Token")
def api_login_user(user: UserPwd, background_tasks: BackgroundTasks, db: Session = Depends(get_db)):
"""
登录接口
:param user:
:param background_tasks:
:param db:
:return:
"""
# 如果返回False则抛出错误
if not check_user(user.username, user.password, db):
raise exception_catch
# 判断redis中key是否存在
if not redispy.get_exists(user.username):
access_token_expires = timedelta(days=ACCESS_TOKEN_EXPIRE_DAYS)
# 创建token
access_token = generate_access_token(
data={"username": user.username}, expiration=access_token_expires
)
# 后台任务执行往redis中写入token
background_tasks.add_task(redispy.set_value, user.username, access_token, is_data=True)
return {"token": access_token, "username": user.username}
# 从redis中读取token
access_token = redispy.get_value(user.username, is_data=True)
return {"token": access_token, "username": user.username}
测试一下两个bug是否修改成功
POST http://127.0.0.1:8086/user/login/
首先测试一下不存在的用户
请求参数:
{
"username": "debugfeng06@qq.com",
"password": "123456"
}
请求结果:
{
"detail": {
"status": 0,
"data": {},
"error_msg": "账号或密码不正确 !",
"error_code": 1000
}
}
最后测试一下密码错误的用户
请求参数:
{
"username": "debugfeng06@qq.com",
"password": "1234"
}
请求结果:
{
"detail": {
"status": 0,
"data": {},
"error_msg": "账号或密码不正确 !",
"error_code": 1000
}
}
今天先聊到这里吧,以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,直接私信留言会及时修正发布;非常期待你的一键 3 连【 点赞、收藏、分享 】哟,谢谢!
未完成,待续……
一直在努力,希望你也是!
微信搜索公众号:就用python



