FastAPI(六十七)实战开发《在线课程学习系统》接口开发--用户登陆接口开发

 源码见:"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统"

接上一篇文章FastAPI(六十六)实战开发《在线课程学习系统》接口开发--用户注册接口开发。这次我们分享实际开发--用户登陆接口开发。

我们先来梳理下逻辑:

1.查询用户是否存在

2.校验密码是否正确

3.密码校验失败记录失败次数

4.60分钟内失败次数大于等于3次,60分钟内不能登陆

5.密码校验通过产生对应的token返回

接着我们去设置pydantic登录参数校验模型,同样添加到user_schemas.py中

class UserLogin(UserBase):"""登录校验模型"""password: str = Field(min_length=8, max_length=16)

这里我们继承的是之前的UserBase。

对应操作数据库查询用户的逻辑我们使用之前注册的时候使用的get_by_username即可。

我们把密码输入失败和token的值放在redis中,那么redis对应的配置,我们在搭建架构时已经配置好了,都放在了.env中:

ENV = "DEV"# mysql
MYSQL_HOST = "10.30.10.36"
MYSQL_PORT = 3306
MYSQL_USERNAME = "root"
MYSQL_PASSWORD = "123456"
MYSQL_DB_DEV = "learn_onsite_system_dev"
MYSQL_DB_TEST = "learn_onsite_system_test"
MYSQL_DB_PRO = "learn_onsite_system_pro"# redis
REDIS_HOST = "10.30.10.36"
REDIS_PORT = "6379"
REDIS_DB = "0"

而且redis初始化相关逻辑之前我是放在了mian.py主文件中,今天我将其单独提取出来维护

"""
-*- encoding=utf-8 -*-
Time: 2024/7/22 16:02
Author: lc
Email: 15101006331@163.com
File: redis.py
"""
from aioredis import Redis, create_redis_pool
from settings.config import REDIS_CONFIGasync def create_redis() -> Redis:return await create_redis_pool(f"redis://:@{REDIS_CONFIG['host']}:{REDIS_CONFIG['port']}/{REDIS_CONFIG['db']}?encoding=utf-8")

再将其导入到main.py中

from middlewares.redis import create_redis@app.on_event("startup")
async def startup_event():app.state.redis = await create_redis()print("init redis success")create_tables()print("init database success")init_roles()print("init roles success")@app.on_event("shutdown")
async def shutdown_event():app.state.redis.close()await app.state.redis.wait_closed()print("redis closed")

我们把token相关配置也配置进去

ENV = "DEV"# mysql
MYSQL_HOST = "10.30.10.36"
MYSQL_PORT = 3306
MYSQL_USERNAME = "root"
MYSQL_PASSWORD = "123456"
MYSQL_DB_DEV = "learn_onsite_system_dev"
MYSQL_DB_TEST = "learn_onsite_system_test"
MYSQL_DB_PRO = "learn_onsite_system_pro"# redis
REDIS_HOST = "10.30.10.36"
REDIS_PORT = "6379"
REDIS_DB = "0"# TOKEN
SECRET_KEY = "08d25e094faa6ca2556c819756bhj9563b93f7099f6f0f4xxd6cf93b33e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

那么产生token的代码如何实现呢

from jose import JWTError, jwt
from settings.config import TOKEN_CONFIGdef create_access_token(data: dict):"""产生token"""to_encode = data.copy()encoded_jwt = jwt.encode(to_encode, TOKEN_CONFIG["secret_key"], algorithm=TOKEN_CONFIG["algorithm"])return encoded_jwt

接下来就是根据逻辑去实现具体的登录逻辑了,在user_method.py中增加如下方法:
 

async def verify_login(request: Request, user: UserLogin, db: Session):logger.info("登录开始了")db_user = get_by_username(db, user.username)if not db_user:logger.warning(f"用户:’{user.username}‘ 不存在")return response(code=100205, message="用户不存在")verify = verify_password(user.password, db_user.password)if verify:redis_user = await request.app.state.redis.get(user.username)if not redis_user:try:token = create_access_token(data={"sub": user.username})except:logger.warning(f"method verify_login error: {format_exc()}")return response(code=100203, message="生产token失败")await request.app.state.redis.set(user.username, token, expire=TOKEN_CONFIG["access_token_expire_time"])return response()return response(code=100202, message="重复登录")else:error_key = user.username + "_password"result = await request.app.state.redis.hgetall(error_key, encoding="utf-8")# 没有查到认为是第一次出现错误,将次数设置为1,时间设置为当前时间if not result:current_time = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S")await request.app.state.redis.hmset_dict(error_key, num=1, time=current_time)return response(code=100206, message="密码错误")# 查到则不是第一次,要分多重情况else:error_num = int(result["num"])num_time = (datetime.now() - datetime.strptime(result["time"], "%Y-%m-%d %H:%M:%S")).seconds / 60# 60分钟内错误没达到3次,错误次数加1if error_num < 3 and num_time < 60:error_num += 1await request.app.state.redis.hmset_dict(error_key, num=error_num)return response(code=100206, message="密码错误")# 超60分钟没有达到3次,错误次数重置为1,时间设置为当前elif error_num < 3 and num_time > 60:error_num = 1num_time = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S")await request.app.state.redis.hmset_dict(error_key, num=error_num, time=num_time)return response(code=100206, message="密码错误")# 60分钟内错误超过3次,错误次数加1,限制60分钟内不可以登录elif error_num >= 3 and num_time < 60:error_num += 1await request.app.state.redis.hmset_dict(error_key, num=error_num)return response(code=100204, message="输入密码错误次数过多,账号暂时锁定,请60分钟后再来登录")# 超60分钟,如果再次输错,将错误次数重置为1,时间设置为当前时间else:error_num = 1num_time = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S")await request.app.state.redis.hmset_dict(error_key, num=error_num, time=num_time)return response(code=100206, message="密码错误")

接下来,在user.py中增加我们的登录接口

@user_router.post("/login", summary="登录")
async def login(request: Request, user: UserLogin, db: Session = Depends(create_db)):return await verify_login(request, user, db)

测试:

①:成功

②:密码错误

③:60分钟内连续3次登录错误

至此,我们的登录接口就完成了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/49266.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面试知识储备-redis和redission

1.redis的使用 引入依赖&#xff0c;自动注解redistemplate即可使用&#xff0c; 默认的redistemplate存入到redis中是字符流的形式&#xff0c;需要配置redistemplate&#xff0c; 如果不想配置&#xff0c;可以使用stringRedistemplate 可以使用string类型&#xff0c;但是…

JCR一区级 | Matlab实现GA-Transformer-LSTM多变量回归预测

JCR一区级 | Matlab实现GA-Transformer-LSTM多变量回归预测 目录 JCR一区级 | Matlab实现GA-Transformer-LSTM多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.【JCR一区级】Matlab实现GA-Transformer-LSTM多变量回归预测&#xff0c;遗传优化算法&#…

Linux中用shell脚本实现用户注册,登录,删除特点

一、说明 Linux中用shell脚本实现用户注册&#xff0c;登录&#xff0c;删除特点&#xff1a;用户和密码是单另储存在一个文件中&#xff0c;程序结束后&#xff0c;下次登录只要存储用denglu.sh 主目录 denglu1.sh 注册功能模块 denglu2.sh 登录功能模块 denglu3.sh…

C++ 双指针与链表

链表中的一些题目可以用双指针解决&#xff0c;我们将这些题目与其他双指针题目做了总结。 非链表题目 替换数字 给定一个字符串 s&#xff0c;它包含小写字母和数字字符&#xff0c;请编写一个函数&#xff0c;将字符串中的字母字符保持不变&#xff0c;而将每个数字字符替…

书生大模型实战营闯关记录----第二关:实现word_count统计文本中word频次

实现word_count统计文本中word频次 请实现一个wordcount函数&#xff0c;统计英文字符串中每个单词出现的次数。返回一个字典&#xff0c;key为单词&#xff0c;value为对应单词出现的次数。 Eg: Input: """Hello world! This is an example. Word coun…

每日刷题记录(codetop版)

7.21 7.22 7.23 复习7.21和7.22

读书的意义

文章目录 引言什么是热恋的人常做的事?写作是什么样的过程?什么是人生的转折点?人生的答案是什么?为什么很多人宁愿痛苦也不改变?回望过去常有的感受是什么?女人可以活成哪种样子?为什么不能轻言放弃?有没有做一件事“最完美的时刻”?如何生活得有滋有味?为什么要尝试…

Eureka在Kubernetes中的部署指南:微服务发现的艺术

标题&#xff1a;Eureka在Kubernetes中的部署指南&#xff1a;微服务发现的艺术 在当今快速发展的云计算时代&#xff0c;微服务架构因其灵活性和可扩展性而受到青睐。Eureka&#xff0c;作为Netflix开源的服务发现框架&#xff0c;已成为微服务架构中的一个关键组件。然而&am…

并发情况导致事务失效的场景

public void test(Pageable request){for (int i 0; i < 100; i) {//新建线程处理new Thread(() -> {userInfoService.testDemo();}).start();} } 这里创建多个线程模拟多并发场景 Transactional(rollbackOn Exception.class) public synchronized void testDemo() {…

一文入门SpringSecurity 5

目录 提示 Apache Shiro和Spring Security 认证和授权 RBAC Demo 环境 Controller 引入Spring Security 初探Security原理 认证授权图示​编辑 图中涉及的类和接口 流程总结 提示 Spring Security源码的接口名和方法名都很长&#xff0c;看源码的时候要见名知意&am…

海外IP代理科普:代理池有什么用?代理池大小的影响

在当今数字化时代&#xff0c;网络爬虫已经成为获取各类信息必不可少的工具。在大规模数据抓取中&#xff0c;使用单一 IP 地址或同一 IP 代理往往会面临抓取可靠性降低、地理位置受限、请求次数受限等一系列问题。为了克服这些问题&#xff0c;构建代理池成为一种有效的解决方…

控制欲过强的Linux小进程

控制欲强?视奸&#xff1f;普通人那才叫视奸&#xff0c;您是皇帝&#xff0c;天下大事无一逃过您的耳目&#xff0c;您想看什么就看什么&#xff0c;臣怀疑他在朋友圈私养兵士&#xff0c;囤积枪甲&#xff0c;蓄意谋反&#xff0c;图谋皇位啊&#xff01; 哈哈哈哈开个玩笑&…

使用GoAccess进行Web日志可视化

运行网站的挑战之一是了解您的 Web 服务器正在做什么。虽然各种监控应用程序可以在您的服务器以高负载或页面响应缓慢运行时提醒您&#xff0c;但要完全了解正在发生的事情&#xff0c;唯一的方法是查看 Web 日志。阅读日志数据页面并了解正在发生的事情可能需要花费大量时间。…

离散型以及连续型随机变量

目录 离散型随机变量 定义与性质 分布律 分布函数 连续型随机变量 定义与性质 概率密度函数 分布函数 多维随机变量 二维离散型随机变量 二维连续型随机变量 常见的连续型分布 离散型随机变量的概率质量函数和概率密度函数之间的关系是什么&#xff1f; 如何计算连…

C++的UI框架和开源项目介绍

文章目录 1.QT2.wxWidgets3.Dear ImGui 1.QT QT的开源项目&#xff1a;QGIS&#xff08;地理信息系统&#xff09; https://github.com/qgis/QGIS?tabreadme-ov-file 2.wxWidgets wxWidgets的开源项目&#xff1a;filezilla https://svn.filezilla-project.org/svn/ wxWidg…

OSI参考模型:解析网络通信的七层框架

引言 在现代计算机网络中&#xff0c;OSI&#xff08;开放式系统互联&#xff09;参考模型是理解和设计网络通信协议的基础。1978年由国际标准化组织&#xff08;ISO&#xff09;提出&#xff0c;OSI模型定义了网络通信的七层结构&#xff0c;每一层都承担着特定的功能&#x…

环形链表的相关证明

141. 环形链表 - 力扣&#xff08;LeetCode&#xff09; 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使…

基于MobileNetv2的垃圾分类函数式自动微分-昇思25天打卡

基于MobileNetv2的垃圾分类 本文档主要介绍垃圾分类代码开发的方法。通过读取本地图像数据作为输入&#xff0c;对图像中的垃圾物体进行检测&#xff0c;并且将检测结果图片保存到文件中。 1、实验目的 了解熟悉垃圾分类应用代码的编写&#xff08;Python语言&#xff09;&a…

推荐推荐两款免费的WIN PE工具,很好用两款免费的WIN PE工具,很好用

上次推荐了三款WIN PE工具​&#xff1a;推荐3款装机必不可少的PE工具箱&#xff0c;全是宝藏工具&#xff0c;千万不要错过-CSDN博客 今天继续推荐两款WIN PE工具。 FirPE FirPE是一款系统预安装环境&#xff08;Windows PE&#xff09;&#xff0c;它具有简约、易操作等特点…

《SeTformer Is What You Need for Vision and Language》

会议&#xff1a;AAAI 年份&#xff1a;2024 论文&#xff1a;DDAE: Towards Deep Dynamic Vision BERT Pretraining - AMinerhttps://www.aminer.cn/pub/6602613613fb2c6cf6c387c2/ddae-towards-deep-dynamic-vision-bert-pretraining 摘要 这篇论文介绍了一种新型的变换器…