这是一套适合Python快速开发的身份管理模块,SoulSeal 取自修仙小说中的「灵魂烙印」。
Project description
SoulSeal
这是适合Python+FastAPI快速集成的身份管理模块,SoulSeal 取自修仙小说中的「灵魂烙印」。模块内部使用了免安装的键值数据库 RocksDB 来高效存取用户数据。
安装
# 使用pip安装
pip install soulseal
# 或使用Poetry安装(推荐)
poetry add soulseal
快速开始
作为独立服务启动
这种方式非常适合你验证 API 的使用方式。
# 直接使用Python模块运行
poetry run python -m soulseal
# 指定主机和端口
poetry run python -m soulseal --host 0.0.0.0 --port 8080
# 使用环境变量配置
SOULSEAL_DATA_DIR=/path/to/data SOULSEAL_PORT=8080 poetry run python -m soulseal
命令行参数
| 参数 | 环境变量 | 说明 | 默认值 |
|---|---|---|---|
| --data-dir | SOULSEAL_DATA_DIR | 数据目录 | ~/.soulseal |
| --host | SOULSEAL_HOST | 主机地址 | 127.0.0.1 |
| --port | SOULSEAL_PORT | 端口 | 8000 |
| --prefix | SOULSEAL_PREFIX | API前缀 | /api |
| --cors-origins | SOULSEAL_CORS_ORIGINS | CORS源列表(逗号分隔) | http://localhost:3000,... |
设计理念
SoulSeal 采用现代化的身份认证架构设计:
- JWT身份验证:使用行业标准的JWT令牌进行身份验证和授权
- 令牌分离设计:
- 访问令牌(Access Token):短期有效(默认5分钟),存储在内存中,用于API请求认证
- 刷新令牌(Refresh Token):长期有效(默认7天),存储在HTTP-only Cookie中,用于获取新的访问令牌
- 无感续订机制:当访问令牌剩余有效期低于25%时,系统自动续订令牌
- 黑名单机制:支持令牌撤销,即使令牌未过期也能立即失效
- 多设备支持:同一用户可在多设备同时登录,每个设备使用独立的令牌
- 内置用户管理:集成了简单的用户管理模块
- 基于角色的访问控制:支持细粒度的权限管理
API端点
SoulSeal提供以下API端点(假设前缀为/api):
| 路径 | 方法 | 描述 | 授权 |
|---|---|---|---|
/api/auth/register |
POST | 用户注册 | 否 |
/api/auth/login |
POST | 用户登录 | 否 |
/api/auth/logout |
POST | 用户退出 | 是 |
/api/auth/change-password |
POST | 修改密码 | 是 |
/api/auth/profile |
GET/POST | 获取/更新用户信息 | 是 |
/api/auth/refresh-token |
POST | 刷新访问令牌(令牌过期时) | 否 |
在FastAPI应用中集成
推荐集成方式
下面展示如何在自己控制的FastAPI应用中集成SoulSeal认证功能:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from pathlib import Path
from voidring import IndexedRocksDB
from soulseal import TokenSDK, UsersManager, mount_auth_api
# 创建自己的FastAPI应用
app = FastAPI(
title="我的应用",
description="集成SoulSeal认证的API",
version="0.1.0"
)
# 配置CORS(如果前端与后端跨域就必须设置)
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
expose_headers=["Authorization"] # 确保前端可以获取到Authorization头
)
# 初始化数据库和认证组件
db_path = Path.home() / ".myapp" / "db"
db_path.mkdir(parents=True, exist_ok=True)
db = IndexedRocksDB(str(db_path))
# 创建令牌SDK和用户管理器
token_sdk = TokenSDK(db=db)
users_manager = UsersManager(db)
# 挂载SoulSeal认证API
mount_auth_api(
app=app,
prefix="/api",
token_sdk=token_sdk,
users_manager=users_manager
)
保护路由的方法
SoulSeal提供了多种方式来保护您的API路由,让您可以根据需求选择最合适的方法:
方法1: 安全路由装饰器(最简洁)
from fastapi import FastAPI, APIRouter
from soulseal import TokenSDK
app = FastAPI()
router = APIRouter()
token_sdk = TokenSDK(db=db)
# 基本认证路由
@token_sdk.secure_route(router, "/secure-route")
async def secure_endpoint():
return {"message": "此路由受到保护"}
# 需要管理员角色的路由
@token_sdk.secure_route(
router,
"/admin-route",
methods=["GET", "POST"], # 可指定多种HTTP方法
)
async def admin_endpoint(token_claims: dict):
# token_claims包含用户信息
return {"message": f"您好,{token_claims.get('username')}"}
# 注册路由
app.include_router(router)
方法2: 使用依赖注入(传统方式)
from fastapi import Depends
# 创建认证依赖
require_user = token_sdk.get_auth_dependency()
require_admin = token_sdk.get_auth_dependency(require_roles=["admin"])
# 基本认证
@router.get(
"/secure-dependency",
openapi_extra={"security": [{"Bearer": []}]}
)
async def secure_with_dependency(user = Depends(require_user)):
return {"message": f"您好,{user.get('username')}"}
# 管理员认证
@router.get(
"/admin-dependency",
openapi_extra={"security": [{"Bearer": []}]}
)
async def admin_with_dependency(user = Depends(require_admin)):
return {"message": "管理员专属内容"}
方法3: 编程式注册(适合批量路由)
from soulseal.start import register_secure_route
async def dynamic_endpoint(token_claims: dict = None):
"""动态创建的受保护端点"""
return {"message": f"您已通过认证,用户ID: {token_claims.get('user_id')}"}
# 注册安全路由
register_secure_route(
app=app,
path="/api/dynamic-route",
endpoint=dynamic_endpoint,
require_user=token_sdk.get_auth_dependency(),
methods=["GET"],
tags=["动态路由"]
)
完整后端演示效果
您可以在启用示例路由的情况下启动应用,查看完整的使用方式:
from soulseal import create_app
app = create_app(
db_path="./data",
title="SoulSeal演示",
description="身份认证系统演示",
cors_origins=["http://localhost:3000"],
prefix="/api",
include_examples=True # 启用示例路由
)
这将添加以下示例路由:
/api/examples/secure-route- 使用安全路由装饰器/api/examples/admin-route- 需要管理员权限(依赖项方式)/api/examples/admin-dependency- 需要管理员权限(直接依赖方式)/api/examples/secure-dependency- 使用依赖注入/api/examples/secure-programmatic- 以编程方式注册的路由
客户端使用
// auth.js - 认证服务
const auth = {
token: localStorage.getItem('auth_token'),
// 登录并保存令牌
async login(username, password) {
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
credentials: 'include'
});
if (!response.ok) throw new Error('登录失败');
// 保存令牌
const authHeader = response.headers.get('Authorization');
if (authHeader?.startsWith('Bearer ')) {
this.token = authHeader.substring(7);
localStorage.setItem('auth_token', this.token);
}
return await response.json();
},
// 创建带认证的请求
async fetch(url, options = {}) {
// 添加认证头
const headers = { ...options.headers };
if (this.token) {
headers['Authorization'] = `Bearer ${this.token}`;
}
// 发送请求
const response = await fetch(url, {
...options,
headers,
credentials: 'include'
});
// 处理自动令牌续订
const newToken = response.headers.get('Authorization');
if (newToken?.startsWith('Bearer ')) {
this.token = newToken.substring(7);
localStorage.setItem('auth_token', this.token);
}
// 处理401错误(令牌过期)
if (response.status === 401) {
// 尝试刷新令牌
const refreshed = await this.refreshToken();
if (refreshed) {
// 使用新令牌重试请求
return this.fetch(url, options);
} else {
// 刷新失败,重定向到登录页
this.logout();
location.href = '/login';
}
}
return response;
},
// 刷新令牌
async refreshToken() {
try {
const response = await fetch('/api/auth/refresh-token', {
method: 'POST',
credentials: 'include'
});
if (!response.ok) return false;
const data = await response.json();
if (data.access_token) {
this.token = data.access_token;
localStorage.setItem('auth_token', this.token);
return true;
}
return false;
} catch (e) {
return false;
}
},
// 注销
logout() {
fetch('/api/auth/logout', {
method: 'POST',
headers: this.token ? { 'Authorization': `Bearer ${this.token}` } : {},
credentials: 'include'
}).finally(() => {
this.token = null;
localStorage.removeItem('auth_token');
});
}
};
// 使用示例
async function getUserProfile() {
const response = await auth.fetch('/api/auth/profile');
if (response.ok) {
const profile = await response.json();
console.log('用户信息:', profile);
return profile;
}
return null;
}
用户管理功能
SoulSeal提供完整的用户管理功能:
- 用户注册与登录:支持用户名、密码和电子邮件注册,密码加密存储
- 多设备支持:同一用户可以在多个设备上同时登录,互不干扰
- 基于角色的访问控制:支持用户角色设置(用户、管理员等)
- 个人资料管理:查看和更新用户信息
- 密码管理:支持修改密码、密码重置等功能
- 会话管理:查看当前登录设备,可以远程注销特定设备
- 账号锁定与激活:管理员可锁定或激活用户账号
安全注意事项
- 默认情况下,访问令牌有效期为5分钟,刷新令牌有效期为7天
- 访问令牌通过Authorization头部传输,刷新令牌存储在HTTP-only Cookie中,增强安全性
- 所有密码均使用bcrypt加密存储,无法还原
- 令牌撤销后会被加入黑名单,即使未过期也无法使用
- 支持HTTPS,生产环境必须启用
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file soulseal-0.1.12.tar.gz.
File metadata
- Download URL: soulseal-0.1.12.tar.gz
- Upload date:
- Size: 30.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.0.0 CPython/3.11.7 Darwin/24.3.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36fc21e786002add71f6933fce59b8ed46aba8b564ccf2c512b9603c87e1bf3a
|
|
| MD5 |
1028a0ad55e1713c353f0a350a653321
|
|
| BLAKE2b-256 |
eaa90962133923d3944a66f6efc451365ac22316dabecfe8a0d05f7e147158ca
|
File details
Details for the file soulseal-0.1.12-py3-none-any.whl.
File metadata
- Download URL: soulseal-0.1.12-py3-none-any.whl
- Upload date:
- Size: 36.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.0.0 CPython/3.11.7 Darwin/24.3.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db00691d9b83faebfdeb615d76b09e0d0404a730e1ab66be0c6e7ef737ffbaeb
|
|
| MD5 |
ba39427eea21a84b0aedab1e2ff6e248
|
|
| BLAKE2b-256 |
e0ed19e247c15b83380f20942b6eb054c8f6a4827750a1dd77c2b53dd7d577bd
|