osr*_*roc 5 firebase blazor google-cloud-firestore blazor-client-side
尝试在 C# (Blazor WASM) 中创建 FirebaseDb 对象在部署到 Firebase 后会引发阻止的混合内容错误。有没有办法强制它使用HTTPS?
错误:
阻止加载混合活动内容“ http://169.254.169.254/ ” dotnet.3.2.0-preview3.20168.1.js:1:163131 ?crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100.webassembly] bla .js:1:36074 未处理的异常呈现组件:类型错误:尝试获取资源时出现网络错误。blazor.webassembly.js:1:36074 WebAssembly.JSException: TypeError: 尝试获取资源时出现网络错误。blazor.webassembly.js:1:36074 在 WebAssembly.Net.Http.HttpClient.WasmHttpMessageHandler.doFetch (System.Threading.Tasks.TaskCompletionSource1[TResult] tcs, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0x257c7e0 + 0x00988> in <filename unknown>:0 blazor.webassembly.js:1:36074
at WebAssembly.Net.Http.HttpClient.WasmHttpMessageHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0x255e648 + 0x00184> in <filename unknown>:0 blazor.webassembly.js:1:36074
at System.Net.Http.HttpClient.FinishSendAsyncBuffered (System.Threading.Tasks.Task1[TResult] sendTask, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationTokenSource cts, System.Boolean disposeCts) <0x256c970 + 0x00278> in :0 blazor.webassembly.js:1:36074 at Google.Apis.Auth .OAuth2.ComputeCredential.IsRunningOnComputeEngineNoCache () <0x24f5570 + 0x0018c> in :0 blazor.webassembly.js:1:36074 at Google.Apis.Auth.OAuth2.DefaultCredentialProvider.CreateDefaultCredentialAsync () <0x2020x0f0x20x0f0x0z0x0z0f .js:1:36074 at Google.Api.Gax.Grpc.ChannelPool.CreateChannelCredentialsUncached () <0x24cf210 + 0x000d8> in :0 blazor.webassembly.js:1:36074 at Google.Api.Gax.Grpc.ChannelPool. Google.Api.Gax.Grpc.ServiceEndpoint 端点,System.Collections.Generic.IEnumerable`1[T] channelOptions) <0x246fb30 + 0x000f4> in :0 blazor.webassembly.js:1:36074 在 Google.Cloud.Firestore.V1.FirestoreClient.CreateAsync(Google.Api.Gax.Grpc.ServiceEndpoint 端点,Google.Cloud.Firestore.V1.FirestoreSettings 设置)<0x246e908 + 0x000ec> 在:0 blazor.webassembly.js: 1:36074 at Google.Cloud.Firestore.FirestoreDb.CreateAsync (System.String projectId, Google.Cloud.Firestore.V1.FirestoreClient client) <0x2449d00 + 0x001d0> in :0 blazor.webassembly.js:1:36074 at blog。 Pages.Index.OnInitializedAsync () <0x2434eb8 + 0x000c8> in :0 blazor.webassembly.js:1:36074 at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync () <0x2330b40 + 0x00104c> in :0 blazor.webassembly.js:1:36074 1:36074 在 Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask (System.Threading.Tasks.Task taskToHandle) <0x247d5b8 + 0x000c2> 中:0 blazor.webassembly.js:1:36074
编码:
protected override async Task OnInitializedAsync()
{
string projectId = "my-poject-id";
FirestoreDb db = await FirestoreDb.CreateAsync(projectId);
}
Run Code Online (Sandbox Code Playgroud)
TL;DR
Firestore 库不应在浏览器上下文中运行。它被开发用于服务器端或管理工具中。该库将允许您在 Firestore 中执行所有操作,并将凭据发送给客户将存在安全风险。
根据您的堆栈跟踪,我假设您正在使用该Google.Cloud.Firestore库。不幸的是,这个库被设计为“服务器客户端库”。在服务器端使用的客户端库。这些“服务器客户端库”的设计与“移动/网络客户端库
”
不同。
移动/网络库将使用 Firebase 的身份验证(用户名/密码、Facebook 等),并且安全模型将应用于该用户上下文。服务器库本质上使您可以访问所有内容。
现在,您遇到的问题是由于 Blazor 不支持此 SDK 引起的。首先,GOOGLE_APPLICATION_CREDENTIALSSDK 依赖的环境变量在 Blazor 应用程序中不可用。如果可用,则无法从浏览器沙箱内访问该文件。
您可以通过使用FirestoreDbBuilder并手动设置JsonCredentials和 来避免这两个问题ProjectId,如下所示:
var builder = new FirestoreDbBuilder();
builder.JsonCredentials = "{\"type\": \"service_account\", \"project_id\": \"\", \"private_key_id\": \"\", \"private_key\": \"\", \"client_email\": \"\", \"client_id\": \"\", \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\", \"token_uri\": \"https://oauth2.googleapis.com/token\", \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\", \"client_x509_cert_url\": \"\" }";
builder.ProjectId = "";
FirestoreDb db = builder.Build();
Run Code Online (Sandbox Code Playgroud)
这将导致下一个问题,所使用的 GRPC 库不支持 Blazor/.NET WASM,从而导致以下堆栈跟踪:
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Unsupported platform.
System.InvalidOperationException: Unsupported platform.
at Grpc.Core.Internal.NativeExtension.GetNativeLibraryFilename () [0x0003f] in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\NativeExtension.cs:231
at Grpc.Core.Internal.NativeExtension.LoadUnmanagedLibrary () [0x0000a] in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\NativeExtension.cs:93
at Grpc.Core.Internal.NativeExtension.LoadNativeMethods () [0x0001a] in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\NativeExtension.cs:120
at Grpc.Core.Internal.NativeExtension..ctor () [0x00006] in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\NativeExtension.cs:40
at Grpc.Core.Internal.NativeExtension.Get () [0x00022] in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\NativeExtension.cs:65
at Grpc.Core.Internal.NativeMethods.Get () [0x00000] in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\NativeMethods.cs:49
at Grpc.Core.GrpcEnvironment.GrpcNativeInit () [0x00016] in T:\src\github\grpc\src\csharp\Grpc.Core\GrpcEnvironment.cs:373
at Grpc.Core.GrpcEnvironment..ctor () [0x0001e] in T:\src\github\grpc\src\csharp\Grpc.Core\GrpcEnvironment.cs:302
at Grpc.Core.GrpcEnvironment.AddRef () [0x00028] in T:\src\github\grpc\src\csharp\Grpc.Core\GrpcEnvironment.cs:78
at Grpc.Core.Channel..ctor (System.String target, Grpc.Core.ChannelCredentials credentials, System.Collections.Generic.IEnumerable`1[T] options) [0x00041] in T:\src\github\grpc\src\csharp\Grpc.Core\Channel.cs:70
at Google.Api.Gax.Grpc.GrpcCore.GrpcCoreAdapter.CreateChannelImpl (System.String endpoint, Grpc.Core.ChannelCredentials credentials, Google.Api.Gax.Grpc.GrpcChannelOptions options) [0x00000] in T:\src\github\gax-dotnet\releasebuild\Google.Api.Gax.Grpc.GrpcCore\GrpcCoreAdapter.cs:34
at Google.Api.Gax.Grpc.GrpcAdapter.CreateChannel (System.String endpoint, Grpc.Core.ChannelCredentials credentials, Google.Api.Gax.Grpc.GrpcChannelOptions options) [0x00024] in T:\src\github\gax-dotnet\releasebuild\Google.Api.Gax.Grpc\GrpcAdapter.cs:29
at Google.Api.Gax.Grpc.ClientBuilderBase`1[TClient].CreateChannel (System.String endpoint, Grpc.Core.ChannelCredentials credentials) [0x00000] in T:\src\github\gax-dotnet\releasebuild\Google.Api.Gax.Grpc\ClientBuilderBase.cs:423
at Google.Api.Gax.Grpc.ClientBuilderBase`1[TClient].CreateCallInvokerAsync (System.Threading.CancellationToken cancellationToken) [0x00145] in T:\src\github\gax-dotnet\releasebuild\Google.Api.Gax.Grpc\ClientBuilderBase.cs:313
at Google.Cloud.Firestore.V1.FirestoreClientBuilder.BuildAsyncImpl (System.Threading.CancellationToken cancellationToken) [0x00033] in /_/apis/Google.Cloud.Firestore.V1/Google.Cloud.Firestore.V1/FirestoreClient.g.cs:285
at Google.Cloud.Firestore.FirestoreDbBuilder.BuildAsync (System.Threading.CancellationToken cancellationToken) [0x0015a] in /_/apis/Google.Cloud.Firestore/Google.Cloud.Firestore/FirestoreDbBuilder.cs:119
at BlazorFirestore.Pages.FetchData.OnInitializedAsync () [0x00061] in C:\Users\niels\source\repos\BlazorFirestore\Pages\FetchData.razor:12
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync () <0x2ff3be8 + 0x0013a> in <filename unknown>:0
Run Code Online (Sandbox Code Playgroud)
可以通过使用Grpc.Net.Client.Web在 Blazor 内部工作的 .NET Grpc 实现来解决此问题。创建以下类(受Google 的 Source启发):
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Unsupported platform.
System.InvalidOperationException: Unsupported platform.
at Grpc.Core.Internal.NativeExtension.GetNativeLibraryFilename () [0x0003f] in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\NativeExtension.cs:231
at Grpc.Core.Internal.NativeExtension.LoadUnmanagedLibrary () [0x0000a] in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\NativeExtension.cs:93
at Grpc.Core.Internal.NativeExtension.LoadNativeMethods () [0x0001a] in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\NativeExtension.cs:120
at Grpc.Core.Internal.NativeExtension..ctor () [0x00006] in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\NativeExtension.cs:40
at Grpc.Core.Internal.NativeExtension.Get () [0x00022] in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\NativeExtension.cs:65
at Grpc.Core.Internal.NativeMethods.Get () [0x00000] in T:\src\github\grpc\src\csharp\Grpc.Core\Internal\NativeMethods.cs:49
at Grpc.Core.GrpcEnvironment.GrpcNativeInit () [0x00016] in T:\src\github\grpc\src\csharp\Grpc.Core\GrpcEnvironment.cs:373
at Grpc.Core.GrpcEnvironment..ctor () [0x0001e] in T:\src\github\grpc\src\csharp\Grpc.Core\GrpcEnvironment.cs:302
at Grpc.Core.GrpcEnvironment.AddRef () [0x00028] in T:\src\github\grpc\src\csharp\Grpc.Core\GrpcEnvironment.cs:78
at Grpc.Core.Channel..ctor (System.String target, Grpc.Core.ChannelCredentials credentials, System.Collections.Generic.IEnumerable`1[T] options) [0x00041] in T:\src\github\grpc\src\csharp\Grpc.Core\Channel.cs:70
at Google.Api.Gax.Grpc.GrpcCore.GrpcCoreAdapter.CreateChannelImpl (System.String endpoint, Grpc.Core.ChannelCredentials credentials, Google.Api.Gax.Grpc.GrpcChannelOptions options) [0x00000] in T:\src\github\gax-dotnet\releasebuild\Google.Api.Gax.Grpc.GrpcCore\GrpcCoreAdapter.cs:34
at Google.Api.Gax.Grpc.GrpcAdapter.CreateChannel (System.String endpoint, Grpc.Core.ChannelCredentials credentials, Google.Api.Gax.Grpc.GrpcChannelOptions options) [0x00024] in T:\src\github\gax-dotnet\releasebuild\Google.Api.Gax.Grpc\GrpcAdapter.cs:29
at Google.Api.Gax.Grpc.ClientBuilderBase`1[TClient].CreateChannel (System.String endpoint, Grpc.Core.ChannelCredentials credentials) [0x00000] in T:\src\github\gax-dotnet\releasebuild\Google.Api.Gax.Grpc\ClientBuilderBase.cs:423
at Google.Api.Gax.Grpc.ClientBuilderBase`1[TClient].CreateCallInvokerAsync (System.Threading.CancellationToken cancellationToken) [0x00145] in T:\src\github\gax-dotnet\releasebuild\Google.Api.Gax.Grpc\ClientBuilderBase.cs:313
at Google.Cloud.Firestore.V1.FirestoreClientBuilder.BuildAsyncImpl (System.Threading.CancellationToken cancellationToken) [0x00033] in /_/apis/Google.Cloud.Firestore.V1/Google.Cloud.Firestore.V1/FirestoreClient.g.cs:285
at Google.Cloud.Firestore.FirestoreDbBuilder.BuildAsync (System.Threading.CancellationToken cancellationToken) [0x0015a] in /_/apis/Google.Cloud.Firestore/Google.Cloud.Firestore/FirestoreDbBuilder.cs:119
at BlazorFirestore.Pages.FetchData.OnInitializedAsync () [0x00061] in C:\Users\niels\source\repos\BlazorFirestore\Pages\FetchData.razor:12
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync () <0x2ff3be8 + 0x0013a> in <filename unknown>:0
Run Code Online (Sandbox Code Playgroud)
现在设置GrpcWebAdapter.Default为FirestoreDbBuilder.GrpcAdapter:
using System;
using Grpc.Core;
using Google.Api.Gax.Grpc;
using Grpc.Net.Client;
using System.Net.Http;
using Grpc.Net.Client.Web;
// you'll need these packages
// Google.Apis.Auth, Google.Cloud.Firestore, Grpc.Net.Client, Grpc.Net.Client.Web
namespace BlazorFirestore
{
// most of the code was borrowed from https://github.com/googleapis/gax-dotnet/blob/master/Google.Api.Gax.Grpc.GrpcNetClient/GrpcNetClientAdapter.cs
public sealed class GrpcWebAdapter : GrpcAdapter
{
// this HttpClient using the GrpcWebHandler and mode is crucial to get Grpc to work for Firestore
private static HttpClient httpClient = new HttpClient(new GrpcWebHandler(GrpcWebMode.GrpcWeb, new HttpClientHandler()));
// Note: this is "Default" rather than "Instance" as we expect to have other factory methods later, e.g. accepting
// an HTTP client factory.
/// <summary>
/// Returns the default instance of this class.
/// </summary>
public static GrpcWebAdapter Default { get; } = new GrpcWebAdapter();
private GrpcWebAdapter()
{
}
/// <inheritdoc />
protected override ChannelBase CreateChannelImpl(string endpoint, ChannelCredentials credentials, Google.Api.Gax.Grpc.GrpcChannelOptions options)
{
var grpcNetClientOptions = ConvertOptions(credentials, options);
var address = ConvertEndpoint(endpoint);
return GrpcChannel.ForAddress(address, grpcNetClientOptions);
}
// Internal for testing
internal static global::Grpc.Net.Client.GrpcChannelOptions ConvertOptions(ChannelCredentials credentials, Google.Api.Gax.Grpc.GrpcChannelOptions options)
{
// If service config resolution is explicitly enabled, throw - we can't support that,
// and users may be depending on it.
if (options.EnableServiceConfigResolution == true)
{
throw new ArgumentException($"{nameof(options.EnableServiceConfigResolution)} is not currently supported in {nameof(GrpcWebAdapter)}");
}
if (options.CustomOptions.Count > 0)
{
throw new ArgumentException($"Custom options are not currently supported in {nameof(GrpcWebAdapter)}");
}
// Options we ignore:
// - PrimaryUserAgent
// - KeepAliveTime
return new global::Grpc.Net.Client.GrpcChannelOptions
{
Credentials = credentials,
MaxReceiveMessageSize = options.MaxReceiveMessageSize,
MaxSendMessageSize = options.MaxSendMessageSize,
// pass the GrpcWeb version of the httpclient
HttpClient = httpClient
};
}
// Internal for testing
internal static string ConvertEndpoint(string endpoint) =>
// Note that we assume HTTPS for any bare address; this feels like a reasonable assumption for now.
endpoint.StartsWith("http:", StringComparison.Ordinal) || endpoint.StartsWith("https:", StringComparison.Ordinal)
? endpoint : $"https://{endpoint}";
}
}
Run Code Online (Sandbox Code Playgroud)
我们又近了一步,但现在我们遇到了 CORS 安全问题,因为这种与 Firestore 通信的方式并非设计为从浏览器运行,并且无法与此 SDK 结合配置 CORS。这些是产生的错误:
Access to fetch at 'https://firestore.googleapis.com/google.firestore.v1.Firestore/Commit' from origin 'https://localhost:5001' 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. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
dotnet.3.2.0.js:1 POST https://firestore.googleapis.com/google.firestore.v1.Firestore/Commit net::ERR_FAILED
blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Status(StatusCode="Internal", Detail="Error starting gRPC call. JSException: TypeError: Failed to fetch", DebugException="WebAssembly.JSException: TypeError: Failed to fetch
at System.Net.Http.WebAssemblyHttpHandler.doFetch (System.Threading.Tasks.TaskCompletionSource`1[TResult] tcs, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0x3c61b60 + 0x00a30> in <filename unknown>:0
at System.Net.Http.WebAssemblyHttpHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0x3c24040 + 0x00174> in <filename unknown>:0
at Grpc.Net.Client.Web.GrpcWebHandler.SendAsyncCore (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x00092] in /_/src/Grpc.Net.Client.Web/GrpcWebHandler.cs:137
at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered (System.Threading.Tasks.Task`1[TResult] sendTask, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationTokenSource cts, System.Boolean disposeCts) <0x3d9ae50 + 0x00134> in <filename unknown>:0
at Grpc.Net.Client.Internal.GrpcCall`2[TRequest,TResponse].RunCall (System.Net.Http.HttpRequestMessage request, System.Nullable`1[T] timeout) [0x0020c] in /_/src/Grpc.Net.Client/Internal/GrpcCall.cs:477 ")
Grpc.Core.RpcException: Status(StatusCode="Internal", Detail="Error starting gRPC call. JSException: TypeError: Failed to fetch", DebugException="WebAssembly.JSException: TypeError: Failed to fetch
at System.Net.Http.WebAssemblyHttpHandler.doFetch (System.Threading.Tasks.TaskCompletionSource`1[TResult] tcs, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0x3c61b60 + 0x00a30> in <filename unknown>:0
at System.Net.Http.WebAssemblyHttpHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) <0x3c24040 + 0x00174> in <filename unknown>:0
at Grpc.Net.Client.Web.GrpcWebHandler.SendAsyncCore (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x00092] in /_/src/Grpc.Net.Client.Web/GrpcWebHandler.cs:137
at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered (System.Threading.Tasks.Task`1[TResult] sendTask, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationTokenSource cts, System.Boolean disposeCts) <0x3d9ae50 + 0x00134> in <filename unknown>:0
at Grpc.Net.Client.Internal.GrpcCall`2[TRequest,TResponse].RunCall (System.Net.Http.HttpRequestMessage request, System.Nullable`1[T] timeout) [0x0020c] in /_/src/Grpc.Net.Client/Internal/GrpcCall.cs:477 ")
at Google.Api.Gax.Grpc.ApiCallRetryExtensions+<>c__DisplayClass0_0`2[TRequest,TResponse].<WithRetry>b__0 (TRequest request, Google.Api.Gax.Grpc.CallSettings callSettings) [0x00051] in T:\src\github\gax-dotnet\releasebuild\Google.Api.Gax.Grpc\ApiCallRetryExtensions.cs:27
at Google.Cloud.Firestore.WriteBatch.CommitAsync (Google.Protobuf.ByteString transactionId, System.Threading.CancellationToken cancellationToken) [0x000b5] in /_/apis/Google.Cloud.Firestore/Google.Cloud.Firestore/WriteBatch.cs:231
at Google.Cloud.Firestore.DocumentReference.SetAsync (System.Object documentData, Google.Cloud.Firestore.SetOptions options, System.Threading.CancellationToken cancellationToken) [0x0004b] in /_/apis/Google.Cloud.Firestore/Google.Cloud.Firestore/DocumentReference.cs:181
at BlazorFirestore.Pages.FetchData.OnInitializedAsync () [0x00166] in C:\Users\niels\source\repos\BlazorFirestore\Pages\FetchData.razor:21
at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync () <0x2ff3be8 + 0x0013a> in <filename unknown>:0
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask (System.Threading.Tasks.Task taskToHandle) <0x3905a50 + 0x000b6> in <filename unknown>:0
Run Code Online (Sandbox Code Playgroud)
当您使用 明确在浏览器中禁用 CORS 时 .\chrome.exe --disable-web-security,结果将是身份验证成功,但实际的 API 将返回 404。
我不清楚为什么它返回 404。我可以Grpc.Net.Client.Web使用 Fiddler 嗅探版本,但默认实现不会被 Fiddler 拦截。看起来网络版本使用了不支持的不同协议/传输。希望有人可以解决下一个问题。
结论:.NET 的 Firestore 库不应该在浏览器沙箱中使用,并且不支持这种方式。
| 归档时间: |
|
| 查看次数: |
1049 次 |
| 最近记录: |