了解并解决 Microsoft Entra 应用程序代理跨源资源共享 (CORS) 问题

跨源资源共享 (CORS) 可能会为通过 Microsoft Entra 应用程序代理发布的应用和 API 带来挑战。 本文讨论 Microsoft Entra 应用程序代理的 CORS 问题和解决方案。

提示

异步 JavaScript 和可扩展标记语言被称为 (AJAX)。 AJAX 在缩写中包含了一个缩写,即可扩展标记语言 (XML) 构成了 AJAX 中的最后一个 X。 AJAX 代表异步 JavaScript 和 XML,XML 代表可扩展标记语言。

浏览器安全性通常会阻止网页向另一个域发出请求。 此限制称为“同源策略”,可防止恶意站点从另一站点读取敏感数据。 但有时你可能想让其他站点调用你的 Web API。 CORS 是一项 W3C 标准,可让服务器放宽同源策略,在拒绝某些跨源请求的同时,允许接受另一些跨源请求。

了解并识别 CORS 问题

如果两个 URL 具有相同的方案、主机和端口 (Request For Comments (RFC) 6454),则它们具有相同的源,例如:

  • http://contoso.com/foo.html
  • http://contoso.com/bar.html

与前两个 URL 相比,这些 URL 具有不同的源:

  • http://contoso.net - 不同的域
  • http://contoso.com:9000/foo.html - 不同的端口
  • https://contoso.com/foo.html - 不同的方案
  • http://www.contoso.com/foo.html - 不同的子域

如果未使用正确的访问控制标头,同源策略会阻止应用程序访问其他源中的资源。 如果 CORS 标头缺失或不正确,则跨源请求会失败。

可以使用浏览器调试工具识别 CORS 问题:

  1. 启动浏览器并浏览到 Web 应用。
  2. 按 F12 以打开调试控制台。
  3. 尝试重现事务,并查看控制台消息。 CORS 冲突会产生有关原点的控制台错误。

在下面的屏幕截图中,选择“试用”按钮导致出现了 CORS 错误消息“在 Access-Control-Allow-Origin 标头中找不到 https://corswebclient-contoso.msappproxy.net”。

CORS issue

应用程序代理的 CORS 挑战

以下示例展示了典型的 Microsoft Entra 应用程序代理 CORS 场景。 内部服务器托管 CORSWebService Web API 控制器,以及调用 CORSWebService 的 CORSWebClient。 有从 CORSWebClientCORSWebService 的异步 JavaScript 和 XML (AJAX) 请求。

On-premises same-origin request

CORSWebClient 应用在本地托管时可正常工作,但是如果通过 Microsoft Entra 应用程序代理进行发布,则无法加载或会出错。 如果通过应用程序代理分别将 CORSWebClientCORSWebService 应用发布为不同的应用,则这两个应用会在不同的域中进行托管。 从 CORSWebClient 发送到 CORSWebService 的 AJAX 请求是跨源请求,因此会失败。

Application proxy CORS request

应用程序代理 CORS 问题的解决方案

你可以采用以下多种方式之一来解决上述 CORS 问题。

选项 1:设置自定义域

使用 Microsoft Entra 应用程序代理自定义域进行同源发布,无需对应用源、代码或标头进行任何更改。

选项 2:发布父目录

发布这两个应用程序的父目录。 如果 Web 服务器上只有两个应用程序,则此解决方案特别有效。 不是单独发布每个应用程序,而是发布公共父目录,这样可使其源相同。

这些示例显示了 CORSWebClient 应用的 Microsoft Entra 应用程序代理页。 当内部 URL 设置为 contoso.com/CORSWebClient 时,应用无法成功向 contoso.com/CORSWebService 目录发出请求,因为它们是跨源的。

Publish app individually

请转而将内部 URL 设置为发布父目录,其中包括 CORSWebClientCORSWebService 目录:

Publish parent directory

生成的应用程序 URL 可有效解决 CORS 问题:

  • https://corswebclient-contoso.msappproxy.net/CORSWebService
  • https://corswebclient-contoso.msappproxy.net/CORSWebClient

选项 3:更新 HTTP 标头

要匹配源请求,请添加 Web 服务的自定义 HTTP 响应头。 对于在 Internet Information Services (IIS) 中运行的网站,请使用 IIS 管理器修改标头。

Add custom response header in IIS Manager

此修改不需要更改任何代码。 可以在 Fiddler 跟踪中验证它。

**Post the Header Addition**\
HTTP/1.1 200 OK\
Cache-Control: no-cache\
Pragma: no-cache\
Content-Type: text/plain; charset=utf-8\
Expires: -1\
Vary: Accept-Encoding\
Server: Microsoft-IIS/8.5 Microsoft-HTTPAPI/2.0\
**Access-Control-Allow-Origin: https://corswebclient-contoso.msappproxy.net**\
X-AspNet-Version: 4.0.30319\
X-Powered-By: ASP.NET\
Content-Length: 17

选项 4:修改应用程序

可以通过使用适当的值添加 Access-Control-Allow-Origin 标头来更改应用程序,以支持 CORS。 添加标头的方式取决于应用程序的代码语言。 更改代码需要的工作量最大。

选项 5:延长访问令牌的生存期

某些 CORS 问题无法解决。 例如,应用程序重定向到 login.microsoftonline.com 进行身份验证,而访问令牌过期。 否则,CORS 调用将失败。 这种场景的一种解决方法是延长访问令牌的生存期,防止其在用户会话期间过期。 有关详细信息,请参阅 Microsoft Entra ID 中可配置的令牌生存期

另请参阅