fastapi 如何解决token到期后重新更新的问题
时间: 2024-09-15 17:05:28 浏览: 80
FastAPI是一个现代、快速(高性能)的Web框架,用于构建APIs,使用Python 3.6+类型提示。在处理安全性时,FastAPI通过依赖注入提供了一个简单而强大的方式来处理认证和授权。通常,使用JWT(JSON Web Tokens)作为Token进行认证。Token到期后需要更新是常见的需求,解决这个问题通常使用以下方法:
1. 使用刷新令牌(Refresh Tokens):首先,生成两个Token,一个是访问令牌(Access Tokens),它具有较短的有效期,另一个是刷新令牌,具有较长的有效期。当访问令牌过期时,客户端可以使用刷新令牌请求一个新的访问令牌,而不需要重新进行身份验证。
2. 使用中间件或依赖:在FastAPI中,可以创建一个中间件或依赖,该中间件或依赖会检查访问令牌的有效性。如果发现令牌已过期,中间件或依赖将使用存储的刷新令牌请求新的访问令牌。
3. 令牌更新逻辑:在后端实现令牌更新的逻辑。当客户端提供有效的刷新令牌时,后端验证刷新令牌,然后生成新的访问令牌和刷新令牌返回给客户端。
以下是使用FastAPI和PyJWT实现token到期后更新的一个简化示例:
```python
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from datetime import datetime, timedelta
from pydantic import BaseModel
# 为了简化,这里直接把密钥放在这里,实际应用中应该使用环境变量或配置文件
SECRET_KEY = "your_secret_key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
class Token(BaseModel):
access_token: str
token_type: str
class TokenData(BaseModel):
username: str | None = None
# 假设的用户验证逻辑
def verify_token(token: str):
# 解析Token并验证是否过期
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
return None
token_data = TokenData(username=username)
except JWTError:
return None
return token_data
app = FastAPI()
@app.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
# 用户验证逻辑,验证成功后发放新的token
user = authenticate_user(form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user.username}, expires_delta=access_token_expires
)
return {"access_token": access_token, "token_type": "bearer"}
@app.get("/users/me")
async def read_users_me(current_user: TokenData = Depends(verify_token)):
return current_user
def create_access_token(data: dict, expires_delta: timedelta | None = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=15)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
def authenticate_user(username: str, password: str):
# 这里应该有实际的验证逻辑,例如查询数据库
# 如果用户验证成功,返回用户信息
return {"username": username}
# 使用OAuth2PasswordBearer来获取当前用户
```
在上述示例中,我们使用了PyJWT库来处理JWT的编码和解码。当用户首次登录时,我们提供一个短期的访问令牌和一个长期的刷新令牌。如果访问令牌到期,客户端可以使用刷新令牌来获取新的访问令牌。请注意,这个示例仅用于说明如何在FastAPI中处理JWT和刷新令牌,并没有包含实际的数据库操作和用户验证逻辑。
阅读全文