1.user_OAuth2.py
from datetime import datetime, timedelta
from jose import JWTError, jwt
from typing import Optional
from fastapi import HTTPException,status
#盐值
SECRET_KEY = "ed970259a19edfedf1010199c7002d183bd15bcaec612481b29bac1cb83d8137"
#加密方式
ALGORITHM = "HS256"
#过期时间
ACCESS_TOKEN_EXPIRE_MINUTES = 10
# 定义一个验证异常的返回
credentials_exception = HTTPException(
#自定义状态码
status_code=status.HTTP_401_UNAUTHORIZED,
#返回信息
detail="认证失败",
#响应头
# 根据OAuth2规范, 认证失败需要在响应头中添加如下键值对
headers={'WWW-Authenticate': "Bearer"}
)
def create_jwt_token(data: dict, expire_delta: Optional[timedelta] = None):
'''加密token'''
# 如果传入了过期时间, 那么就是用该时间, 否则使用默认的时间
expire = datetime.utcnow() + expire_delta if expire_delta else datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
# 需要加密的数据data必须为一个字典类型, 在数据中添加过期时间键值对, 键exp的名称是固定写法
data.update({'exp': expire})
# 进行jwt加密
#data:需要加密的字典类型的数据,key:加密需要使用的秘钥, 也叫做盐值,algorithm:加密的算法, 默认为ALGORITHMS.HS256
token = jwt.encode(claims=data, key=SECRET_KEY, algorithm=ALGORITHM)
print(token)
return token
def decrypt_jwt_token(token):
'''解密token, 返回被加密的字典'''
try:
#解密
payload = jwt.decode(token=token, key=SECRET_KEY, algorithms=[ALGORITHM])
print(f'payload: {payload}')
# 从解密的字典中获取数据
user_id = payload.get('user_id')
nick_name = payload.get('nick_name')
user_name = payload.get('user_name')
#返回解密内容
return {'nick_name': nick_name, 'user_name': user_name, 'user_id': user_id}
except JWTError as e:
# 返回异常自定义验证
raise credentials_exception
user.py
from fastapi import FastAPI,Depends
from pydantic import BaseModel
from utils import mysql
from .user_OAuth2 import create_jwt_token,decrypt_jwt_token
from typing import Union
from fastapi.security import OAuth2PasswordBearer
# 实例化oauth2, tokenUrl给一个生成token的接口
oauth2_scheme = OAuth2PasswordBearer(tokenUrl='/login')
#实例化fastapi
app = FastAPI()
class User(BaseModel):
'''用户类-继承BaseModel模型'''
username:str
password:str
id: Union[str, None] = None
nickname:Union[str,None]=None
def Select_user(user:User):
'''
查询用户是否存在
:param user:用户类
:return: 用户信息 json 或 None
'''
try:
#sql
sql = '''SELECT user_name,password,id,nick_name FROM `user` WHERE user_name=%s AND password=%s'''
#查询
data = mysql.Select(sql, (user.username, user.password))
#赋值
user.username= data[0][0]
user.password= data[0][1]
user.id= data[0][2]
user.nickname= data[0][3]
#返回数据
return user
except Exception as e:
print(e)
#抛出异常返回 none
return None
@app.post('/login')
def login(user: User=Depends(Select_user)):
'''
:param user: 类型为User类,Depends
:return:
'''
if user:
#加密 ,生成token
token = create_jwt_token({'user_id':user.id,'nick_name':user.nickname,'user_name':user.username})
return {'code':200,'access_token':token,'token_type': 'bearer','msg':'登录成功'}
return {'code':100,'msg':'登录失败'}
@app.get('/me')
async def test(token: str = Depends(oauth2_scheme)):
#解密
jwt_token = decrypt_jwt_token(token)
return jwt_token
@app.get('/')
def test(s: str = Depends(oauth2_scheme)):
print(s)
return {'hello': s}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)