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;遗传优化算法&#…

书生大模型实战营闯关记录----第二关:实现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

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

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 日志。阅读日志数据页面并了解正在发生的事情可能需要花费大量时间。…

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…

环形链表的相关证明

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 摘要 这篇论文介绍了一种新型的变换器…

如何将 M.2 HAT+ 与 Raspberry Pi 5 一起使用?

树莓派 M.2 HAT M Key 可以让您连接 M.2 外围设备,如 NVMe 硬盘和其他 PCIe 配件,到树莓派 5 的 PCIe 接口。 M.2 HAT 转接板可以把树莓派 5 上的 PCIe 连接器转换为单个 M.2 M key 边缘连接器。您可以连接任何使用 2230 或 2242 尺寸的设备。M.2 HAT 最大可提供 3A 的电源输出…

Superset 4.0.1导出csv数据中文乱码问题解决

Apache Superset 是一个开源的数据探索和可视化平台,专门用于创建交互式数据报表和仪表盘。它具有强大的数据集成和可视化能力,广泛用于数据分析和商业智能领域。 Superset详细介绍详见 报表系统之Superset-CSDN博客 Superset 导出CSV 默认编码为utf-8,在导出包含中文的文…

jenkins替换配置文件

1.点击首页的【Manage Jenkins】-【Manage Plugins】&#xff0c;在选项【Available plugins】安装 Config File Provider Plugin &#xff0c;安装后重启jenkins 2.安装完成后会有这个图标&#xff0c;点进去 3.点击新建&#xff0c;选择自定义&#xff0c;填入要替换的文件…

深入浅出理解 C 语言中的 qsort 函数

目录 引言 一、什么是qsort 二、函数原型 1.qsort函数 2.比较函数 三、qsort函数使用示例 1.使用qsort排序整形数据 2.使用qsort排序结构数据 总结 引言 在编程中&#xff0c;排序是一个常见且重要的操作。C 语言标准库提供了一系列排序函数&#xff0c;其中 qsort 函…

华为IoTDA解码插件报告错误:The decoding result is empty.data

前面的博文讲过&#xff0c;在使用Neuron上传数据到华为IoTDA的时候没有使用华为的物模型进行解析&#xff0c;因为两者的数据格式不同。具体的说Neuron上传的格式是 {"node": "RS485", "group": "Data", "timestamp": 172…

CSS画边框线带有渐变线和流光边框实例

流光边框css流光边框动画效果_哔哩哔哩_bilibili流光边框css流光边框动画效果_哔哩哔哩_bilibili纯CSS写一个动态流水灯边框的效果&#xff5e;_哔哩哔哩_bilibili荧光边框CSS 动画发光渐变边框特效_哔哩哔哩_bilibili [data-v-25d37a3a] .flow-dialog-custom {background-col…