在某些 Android 设备中,Cordova 不会根据请求发送来源
Cordova doesn't send origin on request in some Android devices
这是一些 android 设备上会发生的问题。
我有一个 Samsung Galaxy A5 (2017)
Google Chrome version 76.0.3809.89
和 Android 版本 8.0.0。
当我第一次在此设备上部署我的 Cordova 应用程序并发出 POST 请求时,我收到有关 CORS 的错误消息:
Access to XMLHttpRequest at 'http://foo.com/bar' from origin 'file://' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
我可以从 Chrome 的开发工具网络选项卡中看到这个 POST 请求没有 origin
参数。
如果我从任务管理器关闭应用程序并再次启动它,我可以成功发出此请求并且 chrome 根据请求发送 'origin' 参数。
如果我从设备的设置中删除应用程序的数据,我可以再次重现该问题。
我完全确定这不是 Content-Security-Policy
或 cordova-whitelist-plugin
配置的问题,因为正如我之前提到的,在其他一些 android 设备上应用程序工作正常。
我需要提及的另一件事是,使用人行横道插件时我没有遇到这个问题。
这是 Chromium webview 上的一个公开错误,有趣的是 76 版本;在此特定版本中,OOR-CORS 在第一个 运行.
中保持启用状态
https://bugs.chromium.org/p/chromium/issues/detail?id=991107#c14
变更列表将直接合并到76分支。
我们遇到了同样的问题。我们首先尝试实施一种解决方法,即应用程序检测到 Chrome 版本。第一次看到版本 76 时,它会自动重启应用程序。大多数用户甚至不会注意到重启。解决方法基于几份报告,其中指出,问题只会在安装 Chroe 76 后的第一个 运行 应用程序期间出现,并在重新启动后永久消失。然而,事实证明,这个问题经常 returns 似乎是随机的,因此解决方法还不够。
幸运的是我们也控制了服务器端,所以我们在那里实施了一个解决方法。基本上我们只接受 file://
原点。此解决方法的安全影响当然取决于各个应用程序,因此请仔细考虑,以防您考虑实施类似的方法。
在我们的例子中,我们使用 ASP.NET,我们面临着额外的挑战。不幸的是,将 file://
指定为源时 EnableCorsAttribute
失败,这符合 CORS 规范,该规范要求每个源中都存在主机名(指定 *
时除外)。所以我们最终想出了以下解决方案(当然是针对ASP.NET):
创建一个 ICorsPolicyProvider
,在原始 file://
的情况下覆盖验证逻辑,并在所有其他情况下委托给嵌套的提供者(原始提供者):
/// <summary>
/// Object that allows clients with `file://` origin. This is used as a workaround
/// for issues on Android devices running Chrome 76. See
/// https://bugs.chromium.org/p/chromium/issues/detail?id=991107#c14
///
/// Simply adding `file://` to the allowed origins list doesn't work, because by
/// specification a hostname is required.
///
/// This workaround should be removed as soon as Chrome 76 distribution has dropped
/// sufficiently.
/// </summary>
// TODO: Remove this workaround once Chrome 76 is not around anymore.
public class CorsPolicyProviderAcceptingFileOrigin : ICorsPolicyProvider
{
public readonly ICorsPolicyProvider inner;
public CorsPolicyProviderAcceptingFileOrigin(ICorsPolicyProvider inner)
{
this.inner = inner;
}
public async Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (
request.Headers.TryGetValues("origin", out IEnumerable<string> origins)
&& origins.SequenceEqual(new[] { "file://" })
)
{
var policy = new CorsPolicy()
{
AllowAnyHeader = true,
AllowAnyMethod = true,
AllowAnyOrigin = false,
};
policy.Origins.Add("file://");
return policy;
}
return await this.inner.GetCorsPolicyAsync(request, cancellationToken);
}
}
然后在WebApiConfig.cs
中这样使用它:
// get the original EnableCorsAttribute
ICorsPolicyProvider cors = ...;
// this is a workaround for Android devices running Chrome 76 and should be removed in future versions.
// See https://bugs.chromium.org/p/chromium/issues/detail?id=991107
cors = new CorsPolicyProviderAcceptingFileOrigin(cors);
config.EnableCors(cors);
我们遇到了同样的问题...AJAX 在我们的 Cordova 项目中第一次冷启动后调用将无法工作。如果我们重新启动应用程序(从后台删除应用程序)那么它就可以工作......这似乎是 Chromium WebView 版本的问题......我发现了一个非常难看的解决方法。使用
https://github.com/dpa99c/cordova-diagnostic-plugin#restart
插件并在第一次冷启动后重新启动应用程序。在 localStorage 中检查冷启动标志。如果找不到,请重新启动应用程序。
这是一些 android 设备上会发生的问题。
我有一个 Samsung Galaxy A5 (2017)
Google Chrome version 76.0.3809.89
和 Android 版本 8.0.0。
当我第一次在此设备上部署我的 Cordova 应用程序并发出 POST 请求时,我收到有关 CORS 的错误消息:
Access to XMLHttpRequest at 'http://foo.com/bar' from origin 'file://' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
我可以从 Chrome 的开发工具网络选项卡中看到这个 POST 请求没有 origin
参数。
如果我从任务管理器关闭应用程序并再次启动它,我可以成功发出此请求并且 chrome 根据请求发送 'origin' 参数。
如果我从设备的设置中删除应用程序的数据,我可以再次重现该问题。
我完全确定这不是 Content-Security-Policy
或 cordova-whitelist-plugin
配置的问题,因为正如我之前提到的,在其他一些 android 设备上应用程序工作正常。
我需要提及的另一件事是,使用人行横道插件时我没有遇到这个问题。
这是 Chromium webview 上的一个公开错误,有趣的是 76 版本;在此特定版本中,OOR-CORS 在第一个 运行.
中保持启用状态https://bugs.chromium.org/p/chromium/issues/detail?id=991107#c14
变更列表将直接合并到76分支。
我们遇到了同样的问题。我们首先尝试实施一种解决方法,即应用程序检测到 Chrome 版本。第一次看到版本 76 时,它会自动重启应用程序。大多数用户甚至不会注意到重启。解决方法基于几份报告,其中指出,问题只会在安装 Chroe 76 后的第一个 运行 应用程序期间出现,并在重新启动后永久消失。然而,事实证明,这个问题经常 returns 似乎是随机的,因此解决方法还不够。
幸运的是我们也控制了服务器端,所以我们在那里实施了一个解决方法。基本上我们只接受 file://
原点。此解决方法的安全影响当然取决于各个应用程序,因此请仔细考虑,以防您考虑实施类似的方法。
在我们的例子中,我们使用 ASP.NET,我们面临着额外的挑战。不幸的是,将 file://
指定为源时 EnableCorsAttribute
失败,这符合 CORS 规范,该规范要求每个源中都存在主机名(指定 *
时除外)。所以我们最终想出了以下解决方案(当然是针对ASP.NET):
创建一个 ICorsPolicyProvider
,在原始 file://
的情况下覆盖验证逻辑,并在所有其他情况下委托给嵌套的提供者(原始提供者):
/// <summary>
/// Object that allows clients with `file://` origin. This is used as a workaround
/// for issues on Android devices running Chrome 76. See
/// https://bugs.chromium.org/p/chromium/issues/detail?id=991107#c14
///
/// Simply adding `file://` to the allowed origins list doesn't work, because by
/// specification a hostname is required.
///
/// This workaround should be removed as soon as Chrome 76 distribution has dropped
/// sufficiently.
/// </summary>
// TODO: Remove this workaround once Chrome 76 is not around anymore.
public class CorsPolicyProviderAcceptingFileOrigin : ICorsPolicyProvider
{
public readonly ICorsPolicyProvider inner;
public CorsPolicyProviderAcceptingFileOrigin(ICorsPolicyProvider inner)
{
this.inner = inner;
}
public async Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (
request.Headers.TryGetValues("origin", out IEnumerable<string> origins)
&& origins.SequenceEqual(new[] { "file://" })
)
{
var policy = new CorsPolicy()
{
AllowAnyHeader = true,
AllowAnyMethod = true,
AllowAnyOrigin = false,
};
policy.Origins.Add("file://");
return policy;
}
return await this.inner.GetCorsPolicyAsync(request, cancellationToken);
}
}
然后在WebApiConfig.cs
中这样使用它:
// get the original EnableCorsAttribute
ICorsPolicyProvider cors = ...;
// this is a workaround for Android devices running Chrome 76 and should be removed in future versions.
// See https://bugs.chromium.org/p/chromium/issues/detail?id=991107
cors = new CorsPolicyProviderAcceptingFileOrigin(cors);
config.EnableCors(cors);
我们遇到了同样的问题...AJAX 在我们的 Cordova 项目中第一次冷启动后调用将无法工作。如果我们重新启动应用程序(从后台删除应用程序)那么它就可以工作......这似乎是 Chromium WebView 版本的问题......我发现了一个非常难看的解决方法。使用
https://github.com/dpa99c/cordova-diagnostic-plugin#restart
插件并在第一次冷启动后重新启动应用程序。在 localStorage 中检查冷启动标志。如果找不到,请重新启动应用程序。