FastAPI实现JWT验证

fastapi是一个异步编程框架,有非常不错的性能,本文介绍如何在 fastapi中实现jwt验证功能

1. 添加依赖

pipenv install pyjwt 'passlib[bcrypt]'

2. 编写一个handle处理jwt所需功能 app/auth.py

import jwt
from fastapi import HTTPException, Security
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from passlib.context import CryptContext
from datetime import datetime, timedelta


class AuthHandler():
    security = HTTPBearer()
    pwd_context = CryptContext(schemes=['bcrypt'], deprecated='auto')
    secret = 'SECRET'

    # 密码加密
    def get_password_hash(self, password):
        return self.pwd_context.hash(password)

   # 密码校验
    def verify_password(self, plain_password, hashed_password):
        return self.pwd_context.verify(plain_password, hashed_password)

    # token生成
    def encode_token(self, user_id):
        payload = {
            'exp': datetime.utcnow()+timedelta(days=0, minutes=120),
            'iat': datetime.utcnow(),
            'sub': user_id
        }
        return str(jwt.encode(payload, self.secret, algorithm='HS256'))

   # token 解码
    def decode_token(self, token):      
        try:
            payload = jwt.decode(token, self.secret, algorithms=['HS256'])
            return payload['sub']
        except jwt.ExpiredSignatureError:
            raise HTTPException(
                status_code=401, detail='Signature has expired')
        except jwt.InvalidTokenError as e:
            raise HTTPException(status_code=401, detail='Invalid token')

    def auth_wrapper(self, oauth: HTTPAuthorizationCredentials = Security(security)):
        return self.decode_token(oauth.credentials)

实现一个注册方法

# 控制器方法
@router.post('/register',status_code=201)
async def register(
    user:UserModel

):
    user = Users(name=user.name,pwd=auth.get_password_hash(user.pwd))
    # logger.info(f'user:{user.name},pwd:{user.pwd}')
    await user.save()
  
    return {'msg':user.id}

# 用户模型类

from tortoise.models import Model
from tortoise import fields

class Users(Model):
    id=fields.IntField(pk=True)
    name=fields.CharField(max_length=20)
    pwd=fields.CharField(max_length=255)
    created_at=fields.DatetimeField(auto_now_add=True)
    updated_at=fields.DatetimeField(auto_Now=True)

用户登录获取Token

@router.post('/login')
async def users(user_vo:UserModel):

    user_db =await Users.get(name=user1.name)
    flag:bool=auth.verify_password(user_vo.pwd,user_db.pwd)
    if not flag:
        raise HTTPException(status_code=401,detail={
            'code':1000,
            'msg':'用户帐号没有授权'})
    token:str=auth.encode_token(user_db.id)
    return {
        "id":user_db.id,
        'name':user_db.name,
        'token':token
    }

路由保护

from fastapi import APIRouter,HTTPException,Body,Form,Depends,BackgroundTasks
from fastapi.responses import FileResponse
from pydantic import BaseModel
from .models.users import Users
from app.auth import AuthHandler
from app.logger import logger



@router.get('/test') #解码成功后返回用户id
async def test(uid=Depends(auth.auth_wrapper)):
    return {'result':'ok'}

你可能感兴趣的:(FastAPI,Python,python)