教程:在 Azure 应用服务中托管启用了 CORS 的 RESTful API

Azure 应用服务提供高度可缩放、自修复的 Web 托管服务。 另外,应用服务还为 RESTful API 提供对跨域资源共享 (CORS) 的内置支持。 本教程介绍如何将 ASP.NET Core API 应用部署到提供 CORS 支持的应用服务。 请使用命令行工具来配置应用,使用 Git 来部署应用。

在本教程中,你将了解如何执行以下操作:

  • 使用 Azure CLI 创建应用服务资源
  • 使用 Git 将 RESTful API 部署到 Azure
  • 启用应用服务 CORS 支持

可以在 macOS、Linux、Windows 中执行本教程中的步骤。

如果没有 Azure 订阅,可在开始前创建一个试用帐户

先决条件

为完成此教程:

创建本地 ASP.NET Core 应用

在此步骤中,请设置本地 ASP.NET Core 项目。 应用服务支持以其他语言编写的适用于 API 的同一工作流。

克隆示例应用程序

  1. 在终端窗口中,通过 cd 转到工作目录。

  2. 运行下列命令,克隆示例存储库。

    git clone https://github.com/Azure-Samples/dotnet-core-api
    cd dotnet-core-api
    

    此存储库包含基于以下教程创建的应用:使用 Swagger 的 ASP.NET Core Web API 帮助页。 它使用 Swagger 生成器来提供 Swagger UI 和 Swagger JSON 终结点。

  3. 确保默认分支为 main

    git branch -m main
    

    提示

    应用服务不需要更改分支名称。 但是,由于大量存储库正在将其默认分支更改为 main(请参阅更改部署分支),因此本教程还介绍如何从 main 部署存储库。

运行应用程序

  1. 运行以下命令,安装所需的包,运行数据库迁移并启动应用程序。

    dotnet restore
    dotnet run
    
  2. 在浏览器中导航到 http://localhost:5000/swagger,以便使用 Swagger UI。

    在本地运行的 ASP.NET Core API

  3. 导航到 http://localhost:5000/api/todo,此时会看到 ToDo JSON 项的列表。

  4. 导航到 http://localhost:5000 并使用浏览器应用。 稍后请将浏览器应用指向应用服务中的远程 API,以便测试 CORS 功能。 浏览器应用的代码位于存储库的 wwwroot 目录中。

  5. 在终端按 Ctrl+C 可随时停止 ASP.NET Core。

备注

请先运行 az cloud set -n AzureChinaCloud 更改云环境,然后才能在 Azure 中国世纪互联中使用 Azure CLI。 若要切换回 Azure 公有云,请再次运行 az cloud set -n AzureCloud

将应用部署到 Azure

在此步骤中,将已连接 SQL 数据库的 .NET Core 应用程序部署到应用服务。

配置本地 Git 部署

可以使用“部署用户” 将 FTP 和本地 Git 部署到 Azure Web 应用。 配置部署用户之后,可对所有 Azure 部署使用此用户。 帐户级部署用户名和密码不同于 Azure 订阅凭据。

若要配置部署用户,请在 Azure Cloud Shell 中运行 az webapp deployment user set 命令。 将 <username> 和 <password> 替换为部署用户名和密码。

  • 用户名必须在 Azure 中唯一,并且对于本地 Git 推送,不能包含“@”符号。
  • 密码必须至少为 8 个字符,且具有字母、数字和符号这三种元素中的两种。
az webapp deployment user set --user-name <username> --password <password>

JSON 输出会将该密码显示为 null。 如果收到 'Conflict'. Details: 409 错误,请更改用户名。 如果收到 'Bad Request'. Details: 400 错误,请使用更强的密码。

请记录你要用于部署 Web 应用的用户名和密码。

创建资源组

资源组是在其中部署和管理 Azure 资源(如 Web 应用、数据库和存储帐户)的逻辑容器。 例如,可以选择在使用完之后通过一个简单的步骤删除整个资源组。

在 Azure CLI 中,使用 az group create 命令创建资源组。 以下示例在“中国北部”位置创建名为“myResourceGroup”的资源组。 要查看“免费”层中应用服务支持的所有位置,请运行 az appservice list-locations --sku FREE 命令。

az group create --name myResourceGroup --location "China North"

通常在附近的区域中创建资源组和资源。

此命令完成后,JSON 输出会显示资源组属性。

创建应用服务计划

使用 az appservice plan create 命令创建应用服务计划。

以下示例在免费定价层中创建名为 myAppServicePlan 的应用服务计划:

az appservice plan create --name myAppServicePlan --resource-group myResourceGroup --sku FREE

创建应用服务计划后,Azure CLI 会显示类似于以下示例的信息:

{ 
  "adminSiteName": null,
  "appServicePlanName": "myAppServicePlan",
  "geoRegion": "China North",
  "hostingEnvironmentProfile": null,
  "id": "/subscriptions/0000-0000/resourceGroups/myResourceGroup/providers/Microsoft.Web/serverfarms/myAppServicePlan",
  "kind": "app",
  "location": "China North",
  "maximumNumberOfWorkers": 1,
  "name": "myAppServicePlan",
  < JSON data removed for brevity. >
  "targetWorkerSizeId": 0,
  "type": "Microsoft.Web/serverfarms",
  "workerTierName": null
} 

创建 Web 应用

myAppServicePlan 应用服务计划中创建一个 Web 应用

在 Azure CLI 中,可以使用 az webapp create 命令。 在以下示例中,将 <app-name> 替换为全局唯一的应用名称(有效字符是 a-z0-9-)。

az webapp create --resource-group myResourceGroup --plan myAppServicePlan --name <app-name> --deployment-local-git

创建 Web 应用后,Azure CLI 会显示类似于以下示例的输出:

Local git is configured with url of 'https://<username>@<app-name>.scm.chinacloudsites.cn/<app-name>.git'
{
  "availabilityState": "Normal",
  "clientAffinityEnabled": true,
  "clientCertEnabled": false,
  "clientCertExclusionPaths": null,
  "cloningInfo": null,
  "containerSize": 0,
  "dailyMemoryTimeQuota": 0,
  "defaultHostName": "<app-name>.chinacloudsites.cn",
  "deploymentLocalGitUrl": "https://<username>@<app-name>.scm.chinacloudsites.cn/<app-name>.git",
  "enabled": true,
  < JSON data removed for brevity. >
}

备注

Git 远程的 URL 将显示在 deploymentLocalGitUrl 属性中,其格式为 https://<username>@<app-name>.scm.chinacloudsites.cn/<app-name>.git。 保存此 URL,后续将会用到。

从 Git 推送到 Azure

回到本地终端窗口,将 Azure 远程功能添加到本地 Git 存储库。 将 <deploymentLocalGitUrl-from-create-step> 替换为在创建 Web 应用中保存的 Git 远程 URL。

git remote add azure <deploymentLocalGitUrl-from-create-step>

使用以下命令推送到 Azure 远程库以部署应用。 当 Git 凭据管理器提示输入凭据时,请确保输入在 配置部署用户 中创建的凭据,而不是用于登录到 Azure 门户的凭据。

git push azure master

此命令可能需要花费几分钟时间运行。 运行时,该命令会显示类似于以下示例的信息:

   Enumerating objects: 83, done.
   Counting objects: 100% (83/83), done.
   Delta compression using up to 8 threads
   Compressing objects: 100% (78/78), done.
   Writing objects: 100% (83/83), 22.15 KiB | 3.69 MiB/s, done.
   Total 83 (delta 26), reused 0 (delta 0)
   remote: Updating branch 'master'.
   remote: Updating submodules.
   remote: Preparing deployment for commit id '509236e13d'.
   remote: Generating deployment script.
   remote: Project file path: .\TodoApi.csproj
   remote: Generating deployment script for ASP.NET MSBuild16 App
   remote: Generated deployment script files
   remote: Running deployment command...
   remote: Handling ASP.NET Core Web Application deployment with MSBuild16.
   remote: .
   remote: .
   remote: .
   remote: Finished successfully.
   remote: Running post deployment command(s)...
   remote: Triggering recycle (preview mode disabled).
   remote: Deployment successful.
   To https://<app_name>.scm.chinacloudsites.cn/<app_name>.git
   * [new branch]      master -> master
   

转到 Azure 应用

  1. 在浏览器中导航到 http://<app_name>.chinacloudsites.cn/swagger,开始使用 Swagger UI。

    在 Azure 应用服务中运行的 ASP.NET Core API

  2. 导航到 http://<app_name>.chinacloudsites.cn/swagger/v1/swagger.json 即可看到已部署 API 的 swagger.json

  3. 导航到 http://<app_name>.chinacloudsites.cn/api/todo 即可看到已部署 API 正在运行。

添加 CORS 功能

接下来,在适用于 API 的应用服务中启用内置的 CORS 支持。

在示例应用中测试 CORS

  1. 在本地存储库中,打开 wwwroot/index.html

  2. 在第 51 中,将 apiEndpoint 变量设置为已部署 API 的 URL (http://<app_name>.chinacloudsites.cn)。 在应用服务中将 <appname> 替换为你的应用名称。

  3. 在本地终端窗口中,再次运行示例应用。

    dotnet run
    
  4. 导航到浏览器应用 (http://localhost:5000)。 在浏览器中打开开发人员工具窗口(在用于 Windows 的 Chrome 中使用 Ctrl+Shift+i),检查“控制台”选项卡。 此时会看到错误消息:No 'Access-Control-Allow-Origin' header is present on the requested resource

    浏览器客户端中的 CORS 错误

    由于浏览器应用 (http://localhost:5000) 和远程资源 (http://<app_name>.chinacloudsites.cn) 的域不匹配,并且由于应用服务中的 API 未发送 Access-Control-Allow-Origin 标头,因此浏览器已阻止跨域内容在浏览器应用中加载。

    在生产中,浏览器应用会有一个公共 URL 而不是 localhost URL,但对 localhost URL 启用 CORS 的方式与对公共 URL 相同。

启用 CORS

在 Windows 终端中,使用 az webapp cors add 命令对客户端的 URL 启用 CORS。 替换 <appname> 占位符。

az webapp cors add --resource-group myResourceGroup --name <app-name> --allowed-origins 'http://localhost:5000'

可以在 properties.cors.allowedOrigins ("['URL1','URL2',...]") 中设置多个客户端 URL。 也可使用 "['*']" 启用所有客户端 URL。

备注

如果应用要求发送凭据(例如 Cookie 或身份验证令牌),则浏览器会要求在响应中包含 ACCESS-CONTROL-ALLOW-CREDENTIALS 标头。 若要在应用服务中启用此功能,请在 CORS 配置中将 properties.cors.supportCredentials 设置为 true。当 allowedOrigins 包含 '*' 时,不能启用此功能。

备注

指定 AllowAnyOriginAllowCredentials 是不安全的配置,可能会导致跨网站请求伪造。 同时使用这两种方法来配置应用时,CORS 服务会返回无效的 CORS 响应。

再次测试 CORS

刷新浏览器应用 (http://localhost:5000)。 “控制台”窗口中的错误消息现在已消失, 可以看到已部署 API 中的数据并与之交互。 远程 API 现在支持对本地运行的浏览器应用使用 CORS。

CORS 在浏览器客户端中成功

恭喜!你在包含 CORS 支持的 Azure 应用服务中运行了 API。

应用服务 CORS 与你的 CORS 的比较

为了提高灵活性,可以使用自己的 CORS 实用程序而不是应用服务 CORS。 例如,可能需要针对不同的路由或方法指定不同的允许的源。 由于应用服务 CORS 允许你为所有 API 路由和方法指定一组接受的源,因此你需要使用自己的 CORS 代码。 请参阅启用跨域请求 (CORS),了解 ASP.NET Core 如何这样做。

备注

请勿尝试将应用服务 CORS 与你自己的 CORS 代码一起使用。 一起使用时,应用服务 CORS 优先级高,你自己的 CORS 代码将无效。

清理资源

若要删除通过此快速入门创建的所有资源,请运行以下命令:

az group delete --name myResourceGroup

后续步骤

你已了解:

  • 使用 Azure CLI 创建应用服务资源
  • 使用 Git 将 RESTful API 部署到 Azure
  • 启用应用服务 CORS 支持

转到下一教程,了解如何对用户进行身份验证和授权。