Casdoor v4:从控制台重写到 MCP Server 与 Agent 身份边界

2026-09-14 16 预计阅读时间: 1 分钟
来源: oschina.net AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:10 分钟

Casdoor 在 2026 年 9 月 1 日发布 v4.0,并于 9 月 9 日迭代至 v4.3。这次升级不只是界面换皮:控制台全面重写,同时加入内置 MCP Server 与 Agent 鉴权能力。对正在把大模型 Agent 接入内部系统的团队来说,这意味着身份平台开始覆盖一种新的主体,即不直接操作浏览器、却会持续调用工具和数据的 AI Agent。

另一个值得注意的节点是,Casdoor 已于 2026 年 2 月 22 日进入 CNCF 云原生全景图,归入 Provisioning 板块下的 Security & Compliance 分类。它仍由 Casbin 社区开发,采用 Go 与 React,使用 Apache 2.0 协议。这些信息不会自动等同于生产成熟度认证,但能帮助团队判断项目定位、治理背景和技术栈是否适合自身环境。

v4 的重点不只在新控制台

控制台全面重写最直接影响管理员的日常操作,例如应用、用户、身份提供方和授权配置的维护体验。升级前不能只检查登录页是否正常,还应覆盖管理员高频工作流,并核对旧版本中的自定义样式、反向代理规则和自动化脚本是否仍然适用。

更重要的变化来自 MCP 与 Agent 鉴权。传统 IAM 通常围绕三类对象设计:人、应用和 API。Agent 引入了更复杂的委托链:用户提出任务,Agent 制定步骤,MCP Server 暴露工具,工具最终访问企业数据。一次工具调用至少需要回答以下问题:

  • 谁启动了这个 Agent 会话?
  • 当前令牌代表用户、Agent,还是二者之间的委托关系?
  • Agent 可以调用哪些 MCP 工具?
  • 工具访问下游 API 时,能否继续沿用原始权限?
  • 调用记录是否足以追溯到用户、Agent、工具和资源?

因此,内置 MCP Server 和 Agent 鉴权的价值不能只按“能否登录”衡量。真正需要验证的是令牌签发、受众限制、权限粒度、生命周期和审计链路。来源摘要没有给出 v4 的具体端点、声明字段或配置格式,部署时应以对应版本文档和实际元数据为准。

把 Agent 当成独立工作负载

一个稳妥的权限模型是同时区分用户身份与 Agent 身份。不要给所有 Agent 共用一个长期管理员令牌,也不要因为请求最初由合法用户发起,就允许 Agent 继承用户的全部权限。

可以把授权拆成三个交集:

  1. 用户本身允许执行的操作。
  2. 当前 Agent 被批准执行的操作。
  3. 当前 MCP Server 对该客户端开放的工具集合。

最终权限应取三者交集。例如,用户可以读取和修改工单,但“日报汇总 Agent”只需要读取权限,那么它拿到的令牌就不应包含写入 scope。对于高风险工具,如删除资源、执行生产命令或导出敏感数据,还应增加短时令牌、人工确认或二次授权。

在多环境部署中,也应为开发、测试和生产分别创建客户端,避免共享 client secret。令牌的 aud 应指向具体 MCP 服务或资源服务器,而不是一个可以被所有内部服务接受的通用值。

可改造的 OIDC 令牌校验示例

下面是一个可以运行的最小 Python 资源服务器。它通过 OIDC/JWKS 校验 Bearer JWT,适合放在 MCP Server 前的 API 网关中,或者改造成服务器自己的鉴权中间件。

这里做了两项明确假设:Casdoor 实例能够提供 OIDC issuer 与 JWKS;Agent 获得的是 JWT access token。实际路径、issuer、audience 和 scope 名称必须根据 Casdoor v4.x 的配置调整,不能直接把示例值用于生产环境。

安装依赖:

python -m venv .venv
. .venv/bin/activate
pip install 'fastapi==0.115.0' 'uvicorn==0.30.6' 'PyJWT[crypto]==2.9.0'

创建 app.py

import os
from typing import Annotated

import jwt
from fastapi import Depends, FastAPI, Header, HTTPException
from jwt import PyJWKClient

ISSUER = os.environ['OIDC_ISSUER'].rstrip('/')
AUDIENCE = os.environ['OIDC_AUDIENCE']
JWKS_URL = os.environ.get('OIDC_JWKS_URL', f'{ISSUER}/.well-known/jwks.json')
REQUIRED_SCOPE = 'mcp:tools:read'

app = FastAPI()
jwks_client = PyJWKClient(JWKS_URL)


def verify_token(authorization: Annotated[str | None, Header()] = None) -> dict:
    if not authorization or not authorization.startswith('Bearer '):
        raise HTTPException(status_code=401, detail='Missing bearer token')

    token = authorization.removeprefix('Bearer ').strip()
    try:
        signing_key = jwks_client.get_signing_key_from_jwt(token)
        claims = jwt.decode(
            token,
            signing_key.key,
            algorithms=['RS256'],
            audience=AUDIENCE,
            issuer=ISSUER,
            options={'require': ['exp', 'iss', 'sub', 'aud']},
        )
    except jwt.PyJWTError as exc:
        raise HTTPException(status_code=401, detail='Invalid token') from exc

    raw_scope = claims.get('scope', '')
    scopes = set(raw_scope.split()) if isinstance(raw_scope, str) else set(raw_scope)
    if REQUIRED_SCOPE not in scopes:
        raise HTTPException(status_code=403, detail='Insufficient scope')
    return claims


@app.get('/mcp/tools')
def list_tools(claims: dict = Depends(verify_token)) -> dict:
    return {
        'subject': claims['sub'],
        'tools': ['ticket.search', 'ticket.read'],
    }

运行前替换三个环境变量。OIDC_JWKS_URL 可以省略,但前提是默认拼接路径与实际部署一致:

export OIDC_ISSUER='https://identity.example.com/your-issuer'
export OIDC_AUDIENCE='internal-mcp-server'
export OIDC_JWKS_URL='https://identity.example.com/path/to/jwks'
uvicorn app:app --host 127.0.0.1 --port 8080

然后使用实际获取的 Agent access token 发起请求:

export ACCESS_TOKEN='replace-with-a-real-access-token'
curl --fail-with-body \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  http://127.0.0.1:8080/mcp/tools

这个示例刻意同时校验签名、issaud、过期时间和 scope。只解码 JWT 或只验证签名是不够的:缺少 audience 校验时,签发给其他服务的令牌也可能被错误接受;缺少 issuer 校验时,服务可能信任了不应信任的签发方。

升级与采用检查表

从 Casdoor 旧版本升级到 v4.x 时,建议先在隔离环境恢复一份生产配置和脱敏数据,再执行完整回归。v4.0 到 v4.3 在数日内连续迭代,也意味着团队应明确锁定版本,不要在生产部署中使用浮动镜像标签。

上线前至少检查这些项目:

  • 验证普通用户登录、退出、令牌刷新和会话失效。
  • 回归新控制台中的用户、应用、角色和身份提供方管理流程。
  • 检查 OAuth/OIDC 回调地址、issuer、JWKS 缓存与密钥轮换。
  • 为每类 Agent 创建独立客户端,并采用短时凭据。
  • 限制 access token 的 audience 和 scope,避免通用内部令牌。
  • 记录用户主体、Agent 客户端、工具名称、目标资源和授权结果。
  • 对写操作、生产操作和敏感数据访问设置额外审批边界。
  • 固定 Casdoor 版本,准备数据库备份、配置备份和回滚步骤。

Casdoor v4 的方向很明确:身份管理的边界正在从人与传统应用扩展到 Agent 和工具调用。是否采用它,不应只看新控制台或项目是否进入 CNCF 全景图,而应通过一条真实的 Agent 到 MCP 工具链,验证令牌模型、最小权限、审计能力和升级兼容性。只有这些环节都经得住测试,新的身份入口才不会变成新的权限旁路。


相关推荐