模拟一个由 Microsoft Entra 保护的 CRUD API

生成应用时,通常会与后端 API 进行交互。 有时,这些 API 尚不可用,或者其他团队正在更新它们以满足最新要求。 为了避免等待,通常会创建一个返回所需数据的模拟 API。 虽然此方法可帮你解除阻碍,但这需要你花些时间生成一个 API,此 API 最终将替换为真正的 API。 当需要使用 Microsoft Entra 保护 API 时,它会变得更加复杂。 为了避免浪费时间,可以使用开发代理模拟 CRUD API 并加快开发速度。

使用CrudApiPlugin,您可以使用内存中的数据存储来模拟CRUD(创建、读取、更新、删除)API。 使用简单的配置文件,可以定义模拟 API 支持的 URL 及其返回的数据。 该插件还支持 CORS,以支持客户端应用程序的跨域使用。 该插件还支持Microsoft Entra 身份验证,因此可以使用 Microsoft Entra 保护模拟 API,并为应用实现与生产环境中相同的身份验证流。

场景

假设你正在构建一个应用,允许用户管理客户。 若要获取数据,需要调用 /customers 后端 API 的终结点。 API 使用 Microsoft Entra 进行保护。 为了避免等待后端团队完成其工作,你决定使用开发代理来模拟 API 并返回所需的数据。

开始之前

首先,使用客户数据创建模拟 CRUD API。 确认 API 正常工作后,可以使用 Microsoft Entra 对其进行保护。

实例 1:使用单一范围模拟通过 Microsoft Entra 进行保护的 CRUD API

在第一个示例中,使用单个作用域保护整个 API。 无论用户是否需要获取客户信息或更新信息,他们都使用相同的权限。

customers-api.json 文件中,添加有关 Entra 的信息。

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v0.24.0/crudapiplugin.schema.json",
  "baseUrl": "https://api.contoso.com/v1/customers",
  "dataFile": "customers-data.json",
  "auth": "entra",
  "entraAuthConfig": {
    "audience": "https://api.contoso.com",
    "issuer": "https://login.microsoftonline.com/contoso.com",
    "scopes": ["api://contoso.com/user_impersonation"]
  },
  "actions": [
    {
      "action": "getAll"
    },
    {
      "action": "getOne",
      "url": "/{customer-id}",
      "query": "$.[?(@.id == {customer-id})]"
    },
    {
      "action": "create"
    },
    {
      "action": "merge",
      "url": "/{customer-id}",
      "query": "$.[?(@.id == {customer-id})]"
    },
    {
      "action": "delete",
      "url": "/{customer-id}",
      "query": "$.[?(@.id == {customer-id})]"
    }
  ]
}

通过将 auth 属性设置为指定的 entra 值,可确保 API 得到 Microsoft Entra 的保护。 在 entraAuthConfig 属性中,指定配置详细信息。 该 audience 属性指定 API 的访问群体、 issuer 属性指定令牌的颁发者,属性 scopes 指定访问 API 所需的范围。 由于在 API 文件的根级别定义 scopes ,因此所有操作都需要相同的范围。

如果尝试在没有具有指定受众、颁发者和范围的令牌的情况下调用 API,则会收到 401 Unauthorized 响应。

注意

在此阶段,开发代理不会验证令牌。 它仅检查令牌是否存在并且具有所需的受众、颁发者和范围。 在早期开发期间,当还没有真正的Microsoft Entra 应用注册并且无法获取真实令牌时,这很方便。

示例 2:使用不同操作的不同范围模拟受 Microsoft Entra 保护的 CRUD API

在许多情况下,不同的 API 操作需要不同的权限。 例如,获取客户信息可能需要与更新客户信息不同的权限。 在此示例中,使用不同的作用域保护不同的 API 操作。

请按如下更新 customers-api.json 文件:

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v0.24.0/crudapiplugin.schema.json",
  "baseUrl": "https://api.contoso.com/v1/customers",
  "dataFile": "customers-data.json",
  "auth": "entra",
  "entraAuthConfig": {
    "audience": "https://api.contoso.com",
    "issuer": "https://login.microsoftonline.com/contoso.com"
  },
  "actions": [
    {
      "action": "getAll",
      "auth": "entra",
      "entraAuthConfig": {
        "scopes": ["api://contoso.com/customer.read"]
      }
    },
    {
      "action": "getOne",
      "url": "/{customer-id}",
      "query": "$.[?(@.id == {customer-id})]",
      "auth": "entra",
      "entraAuthConfig": {
        "scopes": ["api://contoso.com/customer.read"]
      }
    },
    {
      "action": "create",
      "auth": "entra",
      "entraAuthConfig": {
        "scopes": ["api://contoso.com/customer.write"]
      }
    },
    {
      "action": "merge",
      "url": "/{customer-id}",
      "query": "$.[?(@.id == {customer-id})]",
      "auth": "entra",
      "entraAuthConfig": {
        "scopes": ["api://contoso.com/customer.write"]
      }
    },
    {
      "action": "delete",
      "url": "/{customer-id}",
      "query": "$.[?(@.id == {customer-id})]",
      "auth": "entra",
      "entraAuthConfig": {
        "scopes": ["api://contoso.com/customer.write"]
      }
    }
  ]
}

这一次,不在 API 文件的根级别指定 scopes。 而是你需要为每个操作指定参数。 这样,便可以保护具有不同作用域的不同操作。 例如,获取有关客户的信息需要 api://contoso.com/customer.read 范围,而更新客户需要 api://contoso.com/customer.write 范围。

验证令牌

使用 Dev Proxy,您可以模拟受 Microsoft Entra 保护的 CRUD API,并确保您使用的是有效的令牌。 在 Microsoft Entra 中注册应用程序后验证令牌很方便,但团队仍在构建 API。 它允许你更准确地测试应用。

如果希望开发代理验证访问令牌,请在 entraAuthConfig 属性中添加该 validateSigningKey 属性并将其设置为 true

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v0.24.0/crudapiplugin.schema.json",
  "baseUrl": "https://api.contoso.com/v1/customers",
  "dataFile": "customers-data.json",
  "auth": "entra",
  "entraAuthConfig": {
    "audience": "https://api.contoso.com",
    "issuer": "https://login.microsoftonline.com/contoso.com",
    "scopes": ["api://contoso.com/user_impersonation"],
    "validateSigningKey": true
  },
  "actions": [
    {
      "action": "getAll"
    },
    {
      "action": "getOne",
      "url": "/{customer-id}",
      "query": "$.[?(@.id == {customer-id})]"
    },
    {
      "action": "create"
    },
    {
      "action": "merge",
      "url": "/{customer-id}",
      "query": "$.[?(@.id == {customer-id})]"
    },
    {
      "action": "delete",
      "url": "/{customer-id}",
      "query": "$.[?(@.id == {customer-id})]"
    }
  ]
}

如果尝试使用自创建令牌调用 API,则会收到 401 Unauthorized 响应。 开发代理仅允许使用 Microsoft Entra 颁发的有效令牌进行请求。

下一步

详细了解 CrudApiPlugin。

示例

另请参阅相关的开发代理示例: