前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >FastAPI(六十六)实战开发《在线课程学习系统》接口开发--用户登陆接口开发

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

作者头像
雷子
发布2021-10-22 11:55:46
7450
发布2021-10-22 11:55:46
举报

前言

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

正文

我们先来梳理下逻辑

代码语言:javascript
复制
1.查询用户是否存在
2.校验密码是否正确
3.密码校验失败记录失败次数
4.失败次数大于10次,当天不能登陆
5.密码校验通过产生对应的token返回

接着我们去设计pydantic,用于校验用户登陆

代码语言:javascript
复制
class UserLogin(UserBase):
    password: str

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

对应操作数据库的curd我们用之前注册的时候使用的get_user_username即可。

我们把密码输入失败和token放在redis中,那么redis对应的配置。

代码语言:javascript
复制
config.py配置
redishost='127.0.0.1'
redisport='6379'
redisdb=0

我们在main.py增加配置

代码语言:javascript
复制
from fastapi import FastAPI
from aioredis import create_redis_pool, Redis
from routers.user import usersRouter
from routers.websoocket import socketRouter
from routers.file import  fileRouter
from config import *
app = FastAPI()
async def get_redis_pool() -> Redis:
    redis = await create_redis_pool(f"redis://:@"+redishost+":"+redisport+"/"+redisdb+"?encoding=utf-8")
    return redis

@app.on_event("startup")
async def startup_event():
    app.state.redis = await get_redis_pool()


@app.on_event("shutdown")
async def shutdown_event():
    app.state.redis.close()
    await app.state.redis.wait_closed()

我们把产生token的配置也一并配置进去

代码语言:javascript
复制
#config.py
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

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

代码语言:javascript
复制
from jose import JWTError, jwt
#routers/user.py
def create_access_token(data: dict):
    to_encode = data.copy()
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

接下来我们就是去根据逻辑去实现最后的代码了。

代码语言:javascript
复制
@usersRouter.post("/login", response_model=UsersToken)
async def login(request: Request, user: UserCreate, db: Session = Depends(get_db)):
    db_crest = get_user_username(db, user.username)
    if not db_crest:
        logger.info("login:"+user.username+"不存在")
        return  reponse(code=100205,message='用户不存在',data="")
    verifypassowrd = verify_password(user.password, db_crest.password)
    if verifypassowrd:
        useris = await request.app.state.redis.get(user.username)
        if not useris:
            try:
                token = create_access_token(data={"sub": user.username})
            except Exception as e:
                logger.exception(e)
                return reponse(code=100203,message='产生token失败',data='')
            request.app.state.redis.set(user.username, token, expire=ACCESS_TOKEN_EXPIRE_MINUTES * 60)
            return reponse(code=200,message='成功',data={"token":token})
        return reponse(code=100202,message='重复登陆',data='')
    else:
        result=await  request.app.state.redis.hgetall(user.username+"_password", encoding='utf8')
        if not result:
            times = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S")
            request.app.state.redis.hmset_dict(user.username+"_password",num=0,time=times)
        else:
            errornum=int(result['num'])
            numtime=(datetime.now() - datetime.strptime(result['time'],'%Y-%m-%d %H:%M:%S')).seconds / 60
            if errornum<10 and numtime<30:
                #更新错误次数
                errornum += 1
                request.app.state.redis.hmset_dict(user.username + "_password", num=errornum)
                return  reponse(code=100206,data='',message='密码错误')
            elif errornum<10 and numtime>30:
                #次数置于1,时间设置现在时间
                errornum=1
                times = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S")
                request.app.state.redis.hmset_dict(user.username + "_password", num=errornum,time=times)
                return  reponse(code=100206,data='',message='密码错误')
            elif errornum>10 and numtime<30:
                #次数设置成最大,返回
                errornum+=1
                request.app.state.redis.hmset_dict(user.username + "_password", num=errornum)
                return reponse(code=100204,message='输入密码错误次数过多,账号暂时锁定,请30min再来登录',data='')
            else:
                errornum = 1
                times = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S")
                request.app.state.redis.hmset_dict(user.username + "_password", num=errornum, time=times)
                return reponse(code=100206, data='', message='密码错误')

我们按照最后的代码逻辑实现去完成。

一个完整的登陆接口就实现完毕了。

后记

发现问题,解决问题。遇到问题,慢慢解决问题即可。

欢迎关注雷子说测试开发,后续将会持续为大家分享更多的技术知识

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 雷子说测试开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档