目录
九、安全
1、HTTP 基自己份验证(Basic Authentication)
2、Bearer Token
3、Session 管理
1)简单实现
2)当需要session验证的接口会有多个时,使用中间件来做验证。
3)当有大量接口,此中一些需要登录而另一些不需要时,可以使用FastAPI的依赖注入系统来管理这些接口的访问控制。
4、OAuth2 和 OpenID Connect在fastapi中的应用
1)OAuth2
2)OpenID Connect
5、HTTPS 和 TLS 加密
1)获取 SSL/TLS 证书
自署名证书生成(仅用于开辟测试)
2)设置 FastAPI 使用 HTTPS
3)设置 TLS 加密
4)生产环境摆设发起
6、Rate Limiting (速率限定)
九、安全
1、HTTP 基自己份验证(Basic Authentication)
这是最简单的身份验证形式之一,它要求客户端发送带有用户名和暗码的 HTTP 头部。FastAPI 可以很容易地集成这种身份验证方式。使用 hashlib 对暗码进行哈希处理处罚以提高安全性。
- from fastapi import FastAPI, Depends, HTTPException, status
- from fastapi.security import HTTPBasic, HTTPBasicCredentials
- from hashlib import sha256
- app = FastAPI()
- security = HTTPBasic()
- # 假设我们存储的是密码的哈希值
- STORED_USERNAME = "john"
- STORED_PASSWORD_HASH = sha256("secret".encode()).hexdigest()
- def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
- """获取当前用户名,并验证提供的凭据是否正确。"""
- correct_username = credentials.username == STORED_USERNAME
- password_hash = sha256(credentials.password.encode()).hexdigest()
- correct_password = password_hash == STORED_PASSWORD_HASH
- if not (correct_username and correct_password):
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Incorrect user or password",
- headers={"WWW-Authenticate": "Basic"},
- )
- return credentials.username
- @app.get("/users/me")
- def read_user_me(current_username: str = Depends(get_current_username)):
- """获取当前用户的用户名。"""
- return {"username": current_username}
复制代码 请求:
- import requests
- from requests.auth import HTTPBasicAuth
- # 定义服务器地址
- BASE_URL = "http://127.0.0.1:8000"
- def test_get_user_me():
- # 正确的凭据
- correct_credentials = HTTPBasicAuth('john', 'secret')
- response = requests.get(f"{BASE_URL}/users/me", auth=correct_credentials)
- print("Response with correct credentials:")
- print(response.status_code, response.json())
- # 错误的凭据
- incorrect_credentials = HTTPBasicAuth('john', 'wrongpassword')
- response = requests.get(f"{BASE_URL}/users/me", auth=incorrect_credentials)
- print("Response with incorrect credentials:")
- print(response.status_code, response.text)
- if __name__ == "__main__":
- test_get_user_me()
复制代码
2、Bearer Token
Bearer token 身份验证是另一种常见的身份验证方法,通常与 OAuth 2.0 团结使用。FastAPI 提供了内置的支持来处理处罚 bearer tokens。
- from fastapi import FastAPI, Depends, HTTPException, status
- from fastapi.security import OAuth2PasswordBearer
- app = FastAPI()
- oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
- # 假设我们有一个函数来验证 token 是否有效
- def fake_decode_token(token):
- """模拟解码令牌的函数,检查令牌是否有效并返回用户信息"""
- if token == "validtoken":
- return {"username": "john", "scope": "admin"}
- else:
- return None
- async def get_current_user(token: str = Depends(oauth2_scheme)):
- """获取当前用户,如果令牌无效则抛出未授权异常"""
- user = fake_decode_token(token)
- if user is None:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Invalid token",
- headers={"WWW-Authenticate": "Bearer"},
- )
- return user
- @app.get("/users/me")
- def read_user_me(current_user=Depends(get_current_user)):
- """读取当前用户的信息"""
- return current_user
复制代码 请求:
- import requests
- # 定义服务器地址
- BASE_URL = "http://127.0.0.1:8000"
- def test_get_user_me():
- # 正确的令牌
- valid_token = "validtoken"
- headers = {"Authorization": f"Bearer {valid_token}"}
- response = requests.get(f"{BASE_URL}/users/me", headers=headers)
- print("Response with valid token:")
- print(response.status_code, response.json())
- # 错误的令牌
- invalid_token = "invalidtoken"
- headers = {"Authorization": f"Bearer {invalid_token}"}
- response = requests.get(f"{BASE_URL}/users/me", headers=headers)
- print("Response with invalid token:")
- print(response.status_code, response.text)
- if __name__ == "__main__":
- test_get_user_me()
复制代码
3、Session 管理
1)简单实现
- from fastapi import FastAPI, Request, HTTPException, status
- from fastapi.responses import JSONResponse
- from itsdangerous import URLSafeTimedSerializer
- import hashlib
- import os
- def hash_password(password: str) -> str:
- # 生成随机盐
- salt = os.urandom(16)
- # 创建新的哈希对象
- hasher = hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), salt, 100000)
- # 返回盐和哈希值的组合
- return salt.hex() + hasher.hex()
- def verify_password(stored_password: str, provided_password: str) -> bool:
- # 从存储的密码中提取盐
- salt = bytes.fromhex(stored_password[:32])
- # 提取哈希值
- stored_hash = stored_password[32:]
- # 重新计算哈希值
- hasher = hashlib.pbkdf2_hmac('sha256', provided_password.encode('utf-8'), salt, 100000)
- # 比较哈希值
- return hasher.hex() == stored_hash
- app = FastAPI()
- serializer = URLSafeTimedSerializer("SECRET_KEY")
- # 假设的用户数据库
- fake_users_db = {
- "alice": {
- "username": "alice",
- "hashed_password": hash_password("secret_password")
- }
- }
- def authenticate_user(fake_db, username: str, password: str):
- user = fake_db.get(username)
- if not user or not verify_password(user["hashed_password"], password):
- return False
- return user
- @app.post("/login")
- async def login(request: Request):
- data = await request.json()
- username = data.get('username')
- password = data.get('password')
- user = authenticate_user(fake_users_db, username, password)
- if not user:
- raise HTTPException(
- status_code=status.HTTP_401_UNAUTHORIZED,
- detail="Incorrect username or password",
- headers={"WWW-Authenticate": "Bearer"},
- )
- session_token = serializer.dumps(username)
- response = JSONResponse({"message": "Login successful"})
- response.set_cookie(key="session_token", value=sessi
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |