7.3 JWT(JSON Web Token)认证实现
FastAPI初学者教程:JWT认证实现详解
为Python初学者提供的FastAPI JWT认证实现教程,通过生活化类比和简单示例,快速上手JWT认证,建立Web开发信心。
FastAPI初学者教程:JWT认证实现详解
欢迎来到这个面向Python初学者的FastAPI教程!如果你有基本的Python语法知识,但没有Web开发经验,那你就来对地方了。今天,我们将学习如何在FastAPI中实现JWT(JSON Web Token)认证。我会用生活化的类比解释概念,侧重于动手实践,让你快速获得成功。
什么是JWT?生活化类比来帮你
想象一下JWT就像一个数字电影票:当你购买电影票时,售票员给你一张票(JWT),上面有你的座位信息和电影时间。在进入影院时,你出示这张票,检票员检查它的真实性(签名)和有效期,然后让你进去。JWT就是这样一个安全的“数字票”,用于在网络中传递用户信息。
JWT由三部分组成:
- Header:就像票的头部,告诉你这是什么类型的票(例如,JSON格式)。
- Payload:就像票的主要内容,包含用户信息和其他数据(如用户名、过期时间)。
- Signature:就像票的防伪签名,确保票没有被篡改。
简单来说,JWT帮你安全地告诉服务器“我是谁”,无需每次请求都输入密码。
先决条件
确保你已安装Python 3.7或更高版本。如果还没有,请去Python官网下载安装。
第一步:安装必要依赖
打开你的终端或命令行工具,运行以下命令来安装FastAPI和相关库:
pip install fastapi uvicorn python-jose passlib python-multipart
这就像准备你的工具箱:fastapi和uvicorn是构建和运行Web应用的工具,python-jose用于JWT加密,passlib处理密码哈希,python-multipart支持表单数据。
第二步:创建你的第一个FastAPI应用
创建一个新文件夹,比如叫fastapi_jwt_tutorial,然后在里面创建一个Python文件,命名为main.py。打开这个文件,我们将开始写代码。
首先,导入必要的模块:
from fastapi import FastAPI, HTTPException, Depends, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from datetime import datetime, timedelta
from typing import Optional
from pydantic import BaseModel
第三步:设置基本参数
我们将定义一些常量,用于JWT的生成和验证:
# JWT设置
SECRET_KEY = "your-secret-key" # 请在实际应用中替换为强密钥
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30 # 令牌过期时间,单位分钟
# 密码哈希设置
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# OAuth2设置
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
类比:SECRET_KEY就像你家大门的钥匙,只有你知道它,用来锁住JWT的签名部分。
第四步:定义用户模型
创建一个简单的用户模型来模拟用户数据:
# 用户模型
class User(BaseModel):
username: str
email: Optional[str] = None
full_name: Optional[str] = None
disabled: Optional[bool] = None
class UserInDB(User):
hashed_password: str
第五步:模拟数据库
为了简化,我们用一个字典来模拟用户数据库。在实际应用中,你需要连接到真实数据库。
# 模拟数据库
fake_users_db = {
"john": {
"username": "john",
"full_name": "John Doe",
"email": "johndoe@example.com",
"hashed_password": pwd_context.hash("secret"), # 哈希密码
"disabled": False,
}
}
成功时刻:运行代码检查是否有语法错误。如果你没有报错,恭喜你,你已经设置好了基础!
第六步:创建辅助函数
我们将写一些函数来验证用户和生成JWT。
1. 验证密码
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
2. 获取用户
def get_user(db, username: str):
if username in db:
user_dict = db[username]
return UserInDB(**user_dict)
3. 验证用户
def authenticate_user(fake_db, username: str, password: str):
user = get_user(fake_db, username)
if not user:
return False
if not verify_password(password, user.hashed_password):
return False
return user
4. 创建JWT
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
类比:create_access_token就像一个售票机,你输入用户信息,它吐出加密的JWT票。
第七步:创建FastAPI应用和端点
现在,让我们创建FastAPI应用并添加端点。
app = FastAPI()
登录端点:获取JWT
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(fake_users_db, 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"}
成功时刻:运行应用测试登录。首先,启动服务器:
uvicorn main:app --reload
然后,打开浏览器访问 http://127.0.0.1:8000/docs,在交互式文档中找到 /token 端点,尝试用用户名 john 和密码 secret 登录。你应该看到一个JWT令牌返回!
受保护的端点:验证JWT
我们需要一个函数来验证JWT:
def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
user = get_user(fake_users_db, username)
if user is None:
raise credentials_exception
return user
现在,创建一个受保护的端点:
@app.get("/users/me")
async def read_users_me(current_user: User = Depends(get_current_user)):
return current_user
成功时刻:在交互式文档中,登录后获取令牌,然后点击 Authorize 按钮,输入令牌(格式如 Bearer your-token)。之后,访问 /users/me 端点,你应该看到用户信息,证明了JWT认证成功!
第八步:总结和实践建议
恭喜你!你已经成功在FastAPI中实现了JWT认证。让我们回顾一下:
- JWT就像一个安全的数字票,用于认证。
- 我们设置了密钥、过期时间,并创建了登录和受保护的端点。
- 通过模拟数据库,你学会了基本流程。
下一步:
- 尝试添加更多用户或修改数据。
- 学习如何集成真实数据库,如SQLite或PostgreSQL。
- 探索FastAPI的更多功能,如异步支持或依赖注入。
记住,Web开发是一个循序渐进的过程。每次成功运行代码,都是你的“成功时刻”!如果你遇到问题,检查代码或搜索错误信息,网上有很多资源可以帮助你。
希望这个教程帮你建立了信心。继续探索,祝你学习愉快!
注意:在实际部署中,请使用强密钥并妥善管理安全设置。此示例仅用于学习目的。