在今天的数字世界中,API 是现代应用程序的生命线——而伟大的力量伴随着伟大的责任。保护您的 API 不仅仅是锁上前门还不够;需要构建一个强大的安全框架,以确保数据安全的同时提供流畅的用户体验。在这份指南中,我们将探讨如何使用 JSON Web 令牌(JWT)和 OAuth2 来保护您的 API,并辅以实际示例和最佳安全实践。让我们开始吧——因为没有谁喜欢泄露漏洞的 API!
1. 理解 JWT:读懂数字身份标识JSON Web Tokens (JWT) 是紧凑且 URL 安全的令牌,用来在两个实体之间传输声明。可以将它们想象成包含经过验证的用户信息的数字身份证明。
JWT 结构JWT 是 JSON Web Token 的缩写。
JWT由三部分构成:
- 头信息: 指定算法(例如 HS256)和令牌类型。
- 载荷: 包含声明(用户信息、角色、过期时间等)。
- 签名: 确保令牌没有被篡改,通过使用密钥对头信息和载荷进行签名,以确保其完整性。
JWT示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. <!-- 这是JWT的头部部分, 使用了Base64编码的JSON字符串。 -->
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. <!-- 这是JWT的负载部分, 包含了用户信息和其它数据,并经过Base64编码。 -->
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c <!-- 这是JWT的签名部分。 -->
2. OAuth 2.0:现代API的守护者
OAuth2 是一个行业标准的授权协议。OAuth2 并不直接处理凭证,而是将认证过程交给外部提供商,确保一个更安全、更灵活的系统。
OAuth2 的几个关键点- 资源拥有者: 允许访问的用户。
- 客户端: 请求访问的应用。
- 认证服务器: 在验证资源拥有者身份后颁发访问令牌。
- 资源服务器: 托管受保护的 API 并能接受访问令牌。
常见的OAuth2流程,例如密码或授权码授权,最终会发放JWT作为访问令牌(access token),将这两种技术的优势结合起来。
3 在您的API中使用JWT和OAuth2让我们通过一个实际的例子来动手做。我们将用Python的FastAPI框架来展示一个简单API。
第一步:设置你的开发环境首先,创建一个虚拟环境,然后使用pip或其他工具安装FastAPI和Uvicorn。
mkdir secure-api
cd secure-api
python -m venv venv
# 激活虚拟环境:
# macOS/Linux系统下: source venv/bin/activate
# Windows系统下: venv\Scripts\activate
# 在macOS/Linux下用source命令激活
# 在Windows下使用此命令激活
pip install fastapi uvicorn python-jose[cryptography] passlib[bcrypt].
第二步:编写您的 API 代码
创建一个名为 main.py
的文件,并在里面添加以下代码:
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from datetime import datetime, timedelta
from jose import jwt, JWTError
from passlib.context import CryptContext
# 配置如下
SECRET_KEY = "your-very-secret-key" # 请替换为安全的密钥
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
# 设置密码哈希
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# OAuth2 方案用于处理令牌
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
app = FastAPI()
# 模拟用户数据库
fake_users_db = {
"johndoe": {
"username": "johndoe",
"full_name": "John Doe",
"hashed_password": pwd_context.hash("secret"),
"disabled": False,
}
}
# 实用的认证函数
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
def get_user(db, username: str):
if username in db:
return db[username]
return None
def authenticate_user(db, username: str, password: str):
user = get_user(db, username)
if not user or not verify_password(password, user["hashed_password"]):
return None
return user
def create_access_token(data: dict, expires_delta: timedelta = None):
to_encode = data.copy()
expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15))
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
# 令牌接口
@app.post("/token")
async def login_for_access_token(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="用户名或密码不正确",
headers={"WWW-Authenticate": "Bearer"},
)
access_token = create_access_token(data={"sub": user["username"]},
expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
return {"access_token": access_token, "token_type": "bearer"}
# 依赖项以验证当前用户
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="无法验证凭证",
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: dict = Depends(get_current_user)):
return current_user
步骤 3: 运行并测试你的 API
使用 Uvicorn 运行您的 API:
在命令行中输入以下命令来启动服务器:
uvicorn main:app --reload
这样就可以启动带有热重载功能的服务器了。
现在来用一下你最喜欢的API工具(比如Postman或浏览器),。
- 请求 Token: 向
/token
发送你的用户名和密码。 - 访问受保护的路径: 使用返回的 token,在 Authorization 头中添加
Bearer <your_token>
来访问/users/me
。
虽然上面的例子展示了核心的功能,但在实际应用中,保护您的API安全还需遵循一些额外的最佳实践。
- 使用 HTTPS 加密传输中的数据: 通过 HTTPS 传输数据以加密数据。
- 保护密钥安全: 将密钥存储在环境变量或安全保险库中,而不是在源代码中。
- 令牌过期与刷新: 将令牌的有效期保持较短,并实现刷新令牌以减少令牌被泄露的风险。
- 输入验证: 验证所有输入以防止注入攻击。
- 审计与监控: 定期审计日志并设置监控以检测可疑活动。
- 实施基于角色的访问控制 (RBAC),以实现细粒度的权限管理: 考虑集成基于角色的访问控制以实现细粒度授权。
- 定期更新依赖项: 保持库的更新以缓解已知漏洞。
通过使用JWT和OAuth2,你可以用强大的、行业标准的方法来保护你的API。在我们的实际例子中,我们使用FastAPI实现了安全的端点,确保只有经过验证的用户才能访问受保护的资源。记住,安全API的关键不仅仅在于技术,更在于持续地落实最佳实践和严密监控。
今天就让您的API更安全,为用户建立起一个令人放心且充满信心的基础。
如果你发现本指南对你有所帮助,并且想要更深入地了解API安全,别忘了订阅以获取更多实用技巧、教程和实战案例。祝你编码顺利,愿你的token永远有效!
感谢你加入我们的社区在你离开前,
- 记得给作者点赞并关注她 👏
- 关注我们:X | 领英 | YouTube | Newsletter | 播客 | Differ
- 试试 CoFeed,以最智能的方式了解最新的科技资讯 🧪
- 在 Differ 上创建你自己的免费 AI 博客 🚀
- 加入我们的内容创作者 Discord 社区 🧑💻
- 更多内容,请访问 plainenglish.io 和 stackademic.com
共同學(xué)習(xí),寫下你的評(píng)論
評(píng)論加載中...
作者其他優(yōu)質(zhì)文章