浏览器后退按钮上的CORS错误

yas*_*ass 5 cors asp.net-web-api angularjs

我有一个ASP.NET Web API 2服务。并且多个客户端(角度)应用程序与该服务对话。应用程序和服务发布在不同的子域中,如下所示:

service.mydomain.com

app1.mydomain.com

app2.mydomain.com

我使用Microsoft.AspNet.WebApi.Cors-NuGet包启用了CORS,它工作正常,除了一种情况:用户打开一个应用程序(app1.mydomain.com)。然后导航到另一个(app2.mydomain.com)。然后按下浏览器的后退按钮。以下CORS错误:

The 'Access-Control-Allow-Origin' header has a value 'http://app2.mydomain.com' that is not equal to the supplied origin. 
Origin 'http://app1.mydomain.com' is therefore not allowed access
Run Code Online (Sandbox Code Playgroud)

我配置了Microsoft.AspNet.WebApi.Cors-NuGet程序包,如下所示:

public static void Register(HttpConfiguration config)
        {
        var cors = new EnableCorsAttribute(
                //to-do allow cross domains for all maarif.com sites
                origins: "*", //and also tried "http://app1.mydomain.com, http://app2.mydomain.com" gives same result
                headers: "*",
                methods: "*") {SupportsCredentials = true};

            config.EnableCors(cors);
        }
Run Code Online (Sandbox Code Playgroud)

我在服务器上跟踪了Origin标头值。我将以下代码放入服务“ global.asax”中:

protected void Application_BeginRequest()
        {
            var origin = HttpContext.Current.Request.Headers["Origin"];

            if (origin != null )
            {
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", origin);
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "*");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "*");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
            }
        }
Run Code Online (Sandbox Code Playgroud)

当用户单击“ app2.mydomain.com”后退按钮到“ app1.mydomain.com”时出现问题,随请求发送的源是“ app2.mydomain.com”,并且该服务允许访问此内容: HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", 'app2.mydomain.com');

可以解决吗?

请注意,因为请求已通过身份验证,所以我不能输入“ *”。

小智 5

问题是由于浏览器的缓存机制。因为浏览器会使用缓存中的数据,即使对于 AJAX 请求,当您单击 BACK 按钮时也是如此。

为此,浏览器不会重新发送 CORS 预检以检查Access-Control-Allow-Origin上一页的来源。然后它将使用最新的Access-Control-Allow-Origin,即app2.mydomain.com,因此app1.mydomain.com应该失败。

一个简单的解决方案是在 api 查询字符串的末尾添加时间戳或随机字符串,例如:

js:

let url = 'https://service.mydomain.com/xxxxx?v=' + Date.now();
Run Code Online (Sandbox Code Playgroud)

但是它会忽略Access-Control-Max-Age,这使得对service.mydomain.com.

或者,您可以在新窗口中强制打开指向其他来源的所有链接,这样就无法执行 BACK 操作。

除了这些,我找不到任何其他解决方案。

更新:

我后来在这个anwser之后测试了,然后找到了最终的解决方案:

在 中添加以下 HTTP 响应头service.mydomain.com,然后一切正常。

网址:

Cache-Control: no-store,no-cache,must-revalidate
Pragma: no-cache
Run Code Online (Sandbox Code Playgroud)

只需禁用 AJAX 请求的所有缓存。而且 CORS Max-age 也有效。

现在它适用于 Chrome 和 Firefox。我没有尝试其他浏览器,但我认为应该没有什么不同。


fed*_*zzi 0

您是否尝试过在 StratUp.cs 文件中放入以下内容:

var corsPolicy = new CorsPolicy
            {
                AllowAnyMethod = true,
                AllowAnyHeader = true,
                SupportsCredentials = true,
                Origins = { "http://site1.example.com", "http://site2.emaple.com.:38091", "http://localhost:39372" }

            };

            app.UseCors(new CorsOptions
            {
                PolicyProvider = new CorsPolicyProvider
                {
                    PolicyResolver = context => Task.FromResult(corsPolicy)
                }
            });
Run Code Online (Sandbox Code Playgroud)

在你的网络服务器部分的 web.config 中可能是这样的:

<system.webServer>
    <modules>
      <remove name="FormsAuthentication" />
    </modules>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>
Run Code Online (Sandbox Code Playgroud)