You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI集成Jinja2与Keycloak:实现页面访问自动重定向认证求助

解决FastAPI多页网站自动重定向Keycloak登录的方案

核心问题是你当前的依赖在未认证时返回401 JSON错误,而页面访问需要触发重定向到Keycloak登录页。以下是具体实现方案:

1. 配置基础依赖与Keycloak参数

先安装必要依赖:pip install fastapi uvicorn requests python-jose python-multipart

然后定义Keycloak配置和会话中间件(用于跨请求存储token):

from fastapi import FastAPI, Depends, Request, HTTPException
from fastapi.responses import RedirectResponse, TemplateResponse
from fastapi.middleware.session import SessionMiddleware
from jose import JWTError, jwt
from pydantic import BaseModel
import requests

# 替换为你的Keycloak实际配置
KEYCLOAK_REALM = "your-realm-name"
KEYCLOAK_CLIENT_ID = "your-client-id"
KEYCLOAK_CLIENT_SECRET = "your-client-secret"
KEYCLOAK_DOMAIN = "https://your-keycloak-domain.com"
KEYCLOAK_AUTH_ENDPOINT = f"{KEYCLOAK_DOMAIN}/auth/realms/{KEYCLOAK_REALM}/protocol/openid-connect/auth"
KEYCLOAK_TOKEN_ENDPOINT = f"{KEYCLOAK_DOMAIN}/auth/realms/{KEYCLOAK_REALM}/protocol/openid-connect/token"
KEYCLOAK_CALLBACK_URL = "http://localhost:8000/callback"

app = FastAPI()
# 会话中间件的secret_key请用随机安全字符串,生产环境不要硬编码
app.add_middleware(SessionMiddleware, secret_key="your-strong-session-secret")

# 用户信息模型
class User(BaseModel):
    username: str
    realm_roles: list[str]

2. 修改认证依赖实现自动重定向

重写get_user_info依赖,当检测到未认证或token无效时,直接触发重定向到Keycloak登录页:

def get_user_info(request: Request):
    access_token = request.session.get("access_token")
    
    # 无token则触发登录重定向
    if not access_token:
        auth_url = (
            f"{KEYCLOAK_AUTH_ENDPOINT}?response_type=code"
            f"&client_id={KEYCLOAK_CLIENT_ID}"
            f"&redirect_uri={KEYCLOAK_CALLBACK_URL}"
            f"&scope=openid+profile+roles"
            # 存储当前访问的页面,认证后返回原页面
            f"&state={request.url.path}"
        )
        raise HTTPException(
            status_code=307,
            headers={"Location": auth_url}
        )
    
    # 验证并解析token
    try:
        # 如果Keycloak用RS256算法,需要从JWKS端点获取公钥,此处简化为HS256,根据实际配置调整
        payload = jwt.decode(
            access_token,
            KEYCLOAK_CLIENT_SECRET,
            algorithms=["HS256"],
            audience=KEYCLOAK_CLIENT_ID
        )
        return User(
            username=payload.get("preferred_username"),
            realm_roles=payload.get("realm_access", {}).get("roles", [])
        )
    except JWTError:
        # token无效,清除会话并重定向登录
        request.session.pop("access_token", None)
        raise HTTPException(
            status_code=307,
            headers={"Location": KEYCLOAK_AUTH_ENDPOINT}
        )

3. 实现回调接口处理授权码交换

添加回调接口接收Keycloak返回的授权码,交换为access token并存入会话:

@app.get("/callback")
async def keycloak_callback(request: Request, code: str, state: str = "/"):
    # 用授权码交换access token
    token_payload = {
        "grant_type": "authorization_code",
        "code": code,
        "redirect_uri": KEYCLOAK_CALLBACK_URL,
        "client_id": KEYCLOAK_CLIENT_ID,
        "client_secret": KEYCLOAK_CLIENT_SECRET
    }
    token_response = requests.post(KEYCLOAK_TOKEN_ENDPOINT, data=token_payload)
    
    if token_response.status_code != 200:
        return TemplateResponse("login_error.html", {"request": request, "error": token_response.text})
    
    token_data = token_response.json()
    request.session["access_token"] = token_data.get("access_token")
    
    # 重定向回用户最初访问的页面(通过state参数传递)
    return RedirectResponse(url=state)

4. 保护你的页面接口

现在用修改后的依赖保护页面接口,访问时会自动重定向到Keycloak登录:

@app.get("/secure")
async def secure_page(request: Request, user: User = Depends(get_user_info)):
    return TemplateResponse(
        "secure.html",
        {
            "request": request,
            "username": user.username,
            "user_roles": user.realm_roles
        }
    )

关键注意事项

  • Keycloak客户端配置:确保客户端的「Valid Redirect URIs」包含你的回调URL(如http://localhost:8000/callback),否则Keycloak会拒绝回调请求。
  • Token算法:如果你的Keycloak使用RS256非对称加密,需要从Keycloak的JWKS端点获取公钥来验证token,不要直接用客户端密钥。
  • 会话安全:生产环境中SessionMiddleware的secret_key要使用随机生成的安全字符串,避免硬编码;同时可以配置会话过期时间。

内容的提问来源于stack exchange,提问作者Tema Torg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 13:17:02