Skip to main content

生产可用的 Python 统一认证 SDK,支持 Django 和 FastAPI

Project description

ChewyAuthSDK

生产可用的 Python 统一认证 SDK

统一 Keycloak JWT 校验逻辑,同时支持 Django 和 FastAPI。

Python Version License


🎯 核心特性

  • 统一 Keycloak JWT 校验 - 基于 RS256 + JWKS
  • 同时支持 Django 和 FastAPI - 一套 SDK 适配两大框架
  • 独立校验 - 无需 Gateway,无需 introspection API
  • 高性能 - 本地 JWT 解析 + JWKS 缓存
  • 完整透传 Claims - 保留 Keycloak 原始用户信息
  • 开箱即用 - 一行配置即可启用

📦 安装

# 基础安装(仅 JWT 校验)
pip install chewy-auth-sdk

# Django 项目
pip install chewy-auth-sdk[django]

# FastAPI 项目
pip install chewy-auth-sdk[fastapi]

# 同时支持 Django 和 FastAPI
pip install chewy-auth-sdk[all]

🚀 快速开始

1. 配置 SDK

在项目启动时配置一次即可:

from chewy_auth_sdk import configure

configure(
    KEYCLOAK_ISSUER="https://keycloak.example.com/realms/your-realm",
    KEYCLOAK_AUDIENCE="account",  # 可选
    CACHE_TTL=300,  # JWKS 缓存时间(秒)
)

2. Django 集成

2.1 添加 Middleware

settings.py 中添加:

MIDDLEWARE += [
    "chewy_auth_sdk.middleware.django.ChewyAuthMiddleware",
]

2.2 在视图中使用

from django.http import JsonResponse

def my_view(request):
    # request.user 是 AuthUser 对象或 None
    if request.user is None:
        return JsonResponse({"error": "Not authenticated"}, status=401)
    
    return JsonResponse({
        "username": request.user.username,
        "email": request.user.email,
        "roles": request.user.roles,
    })

2.3 使用装饰器进行权限控制

from chewy_auth_sdk.adapters.django import require_auth, require_role

@require_auth
def protected_view(request):
    return JsonResponse({"message": "Authenticated user only"})

@require_role("admin")
def admin_view(request):
    return JsonResponse({"message": "Admin only"})

3. FastAPI 集成

3.1 添加 Middleware

from fastapi import FastAPI
from chewy_auth_sdk.middleware.fastapi import ChewyAuthMiddleware

app = FastAPI()
app.add_middleware(ChewyAuthMiddleware)

3.2 在路由中使用

from fastapi import Request, Depends, HTTPException
from chewy_auth_sdk.adapters.fastapi import get_current_user, require_auth
from chewy_auth_sdk import AuthUser

@app.get("/profile")
def get_profile(request: Request):
    # request.state.user 是 AuthUser 对象或 None
    user = request.state.user
    if user is None:
        raise HTTPException(status_code=401, detail="Not authenticated")
    
    return {
        "username": user.username,
        "email": user.email,
        "roles": user.roles,
    }

# 使用 Dependency
@app.get("/me")
def get_me(user: AuthUser = Depends(require_auth)):
    return {"username": user.username}

3.3 使用 Dependency 进行权限控制

from chewy_auth_sdk.adapters.fastapi import require_role, require_any_role

@app.get("/admin")
def admin_endpoint(user: AuthUser = Depends(require_role("admin"))):
    return {"message": "Admin only"}

@app.get("/moderation")
def moderation_endpoint(
    user: AuthUser = Depends(require_any_role("admin", "moderator"))
):
    return {"message": "Admin or moderator"}

📚 核心概念

AuthUser 对象

所有认证成功的请求都会得到一个 AuthUser 对象:

class AuthUser:
    raw_claims: dict        # Keycloak 原始 claims(完整透传)
    sub: str                # 用户唯一标识
    username: str           # 用户名
    email: str | None       # 邮箱
    roles: list[str]        # 角色列表
    
    # 便捷方法
    def has_role(self, role: str) -> bool
    def has_any_role(self, *roles: str) -> bool
    def has_all_roles(self, *roles: str) -> bool

Token 校验流程

  1. 提取 Token - 从 Authorization: Bearer <token> header 中提取
  2. 获取公钥 - 从 Keycloak JWKS endpoint 获取(带缓存)
  3. 校验签名 - 使用 RS256 算法校验
  4. 校验 Claims - 验证 expissaud
  5. 构造用户对象 - 提取用户信息和角色

为什么不使用 Introspection?

不推荐 Introspection 的原因:

  • 每次请求都需要调用 Keycloak API(性能差)
  • 增加 Keycloak 服务器负载
  • 增加网络延迟
  • 单点故障风险

推荐使用 JWT + JWKS:

  • 本地校验,性能高
  • JWKS 缓存,减少网络请求
  • 无需依赖 Keycloak 可用性
  • 符合 OAuth2 / OIDC 标准最佳实践

⚙️ 高级配置

完整配置选项

from chewy_auth_sdk import configure

configure(
    # Keycloak 配置(必填)
    KEYCLOAK_ISSUER="https://keycloak.example.com/realms/your-realm",
    
    # Audience 校验(可选)
    KEYCLOAK_AUDIENCE="account",  # 如果不提供,不校验 audience
    VERIFY_AUDIENCE=True,  # 是否校验 audience
    
    # JWKS 配置(可选,自动推导)
    KEYCLOAK_JWKS_URI=None,  # 默认:{ISSUER}/protocol/openid-connect/certs
    CACHE_TTL=300,  # JWKS 缓存时间(秒)
    
    # Token 校验(可选)
    VERIFY_EXPIRATION=True,  # 是否校验 token 过期时间
    
    # 角色提取(可选)
    ROLES_CLAIM_PATH="realm_access.roles",  # 角色在 JWT 中的路径
    
    # Header 透传(可选,不推荐)
    ENABLE_HEADER_PASSTHROUGH=False,  # 是否启用 Gateway header 透传
    HEADER_USER_SUB="X-User-Sub",
    HEADER_USER_NAME="X-User-Name",
    HEADER_USER_ROLES="X-User-Roles",
)

Header 透传模式(可选)

如果你使用 Gateway 并希望透传用户信息,可以使用:

# Django
MIDDLEWARE += [
    "chewy_auth_sdk.middleware.django.ChewyAuthMiddlewareWithHeaderPassthrough",
]

# FastAPI
from chewy_auth_sdk.middleware.fastapi import ChewyAuthMiddlewareWithHeaderPassthrough
app.add_middleware(ChewyAuthMiddlewareWithHeaderPassthrough)

自定义角色路径

如果你的角色不在 realm_access.roles,可以自定义:

configure(
    KEYCLOAK_ISSUER="...",
    ROLES_CLAIM_PATH="resource_access.my-client.roles",  # 自定义路径
)

🧪 测试

# 安装开发依赖
pip install -e ".[dev]"

# 运行测试
pytest

📖 架构说明

项目结构

ChewyAuthSDK/
├── chewy_auth_sdk/
│   ├── __init__.py          # 公共 API
│   ├── settings.py          # 全局配置管理
│   ├── exceptions.py        # 统一异常定义
│   ├── jwks.py              # JWKS 管理和缓存
│   ├── token.py             # JWT 校验和 AuthUser
│   ├── context.py           # 请求上下文(可选)
│   ├── middleware/
│   │   ├── django.py        # Django Middleware
│   │   └── fastapi.py       # FastAPI Middleware
│   └── adapters/
│       ├── django.py        # Django 装饰器和工具
│       └── fastapi.py       # FastAPI Dependency 和工具
├── pyproject.toml
└── README.md

设计原则

  1. 职责分离 - 每个模块只做一件事
  2. 框架无关 - 核心逻辑不依赖 Django/FastAPI
  3. 易于扩展 - 可轻松支持新框架
  4. 生产就绪 - 异常处理、缓存、性能优化

🚫 明确禁止

ChewyAuthSDK 只做 Token 校验不实现以下功能:

  • ❌ 登录 / 跳转到 Keycloak
  • ❌ Refresh Token 处理
  • ❌ 用户信息存储(数据库)
  • ❌ Keycloak Admin API 调用
  • ❌ 强制依赖 Gateway

如需这些功能,请直接使用 Keycloak 官方库或其他专用工具。


🤝 贡献

欢迎提交 Issue 和 Pull Request!


📄 License

MIT License


🔗 相关链接


❓ FAQ

Q: 为什么不使用 Keycloak Python Adapter?

A: Keycloak 官方 Python Adapter 主要面向 OIDC 登录流程,对于纯 API 认证(微服务)场景过于复杂。ChewyAuthSDK 专注于 JWT 校验,更轻量、更灵活。

Q: 可以在生产环境使用吗?

A: 是的,ChewyAuthSDK 设计目标就是生产可用。包含完整的异常处理、缓存机制、性能优化。

Q: 如何处理 Token 过期?

A: Token 过期会抛出 TokenExpiredError,Middleware 会返回 401。客户端应该刷新 Token 后重试。

Q: 支持多个 Realm 吗?

A: 当前版本只支持单个 Realm。如需多 Realm,建议为每个服务独立配置 SDK。

Q: 性能如何?

A: JWT 本地校验 + JWKS 缓存,单次请求耗时 < 1ms。JWKS 缓存默认 5 分钟,可自定义。


Enjoy coding with ChewyAuthSDK! 🎉

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

chewy_auth_sdk-0.1.0.tar.gz (26.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

chewy_auth_sdk-0.1.0-py3-none-any.whl (20.2 kB view details)

Uploaded Python 3

File details

Details for the file chewy_auth_sdk-0.1.0.tar.gz.

File metadata

  • Download URL: chewy_auth_sdk-0.1.0.tar.gz
  • Upload date:
  • Size: 26.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.5

File hashes

Hashes for chewy_auth_sdk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d90cf838b7c63baddc55f7b0dbb6e83fe40fa88892c8967d8a25b6cc6235830a
MD5 0c9f603d2e8ca04adcba6d34fc64a979
BLAKE2b-256 9f6b36747dc48f39e4928d47ca36e7bf5909d53638904db7aec99a9fb988d585

See more details on using hashes here.

File details

Details for the file chewy_auth_sdk-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for chewy_auth_sdk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 390b293b8bba048c8533d43012d5efcc767c9925d8cebcd7251c6472133b7f82
MD5 f62ea377aa521a6f78f80645c8e9afa2
BLAKE2b-256 e034fbc5e99a972d4693bce3721c361dfe2e29ccc361532e5d69a4c0e2f8fd09

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page