【问题标题】:Blazor Server SignalR hub fails on StartAsync due to Azure ADB2C由于 Azure ADB2C,Blazor Server SignalR 集线器在 StartAsync 上失败
【发布时间】:2021-06-12 06:28:29
【问题描述】:

我创建了一个 Blazor 服务器应用程序以开始学习 Blazor 和一些更新的技术。我跟着微软的集线器聊天教程一起学习。事情很顺利。然后我添加了一些基本的 cookie 身份验证,事情还在继续。然后,我遵循了 Carl Franklin 在 Blazor Train 上关于将应用程序连接到 Azure AD B2C 的教程。它可以工作,除了应用程序的聊天中心部分。该应用程序的所有其他部分都可以正常工作并显示用户的信息。

我几乎可以肯定"hubconnection" 失败了,因为它没有进行身份验证,因为它没有获取访问令牌。失败发生在await hubConnection.StartAsync(); 行,错误为System.Text.Json.JsonReaderException: '<' is an invalid start of a value。我很确定 HTML 会返回 403 消息或类似消息。

所以我想我在技术上有 2 个问题:

  1. 如何查看导致HubConnectionBuilder 出错的value?即使我设置断点,我也永远看不到导致它阻塞的值是什么。

  2. 如何将访问令牌传递给 HubConnectionBuilder?

我发现了很多“方法”来做到这一点,要么已经过时,要么我无法工作:

Uses AddAzureADB2CBearer which is deprecated

Passes parameters to App which I can't get to work

Is for Azure AD, not B2C

这就是使用 Cookie 身份验证的原因:

    hubConnection = new HubConnectionBuilder()
    .WithUrl(
        NavigationManager.ToAbsoluteUri("/chathub"),
                config => config.UseDefaultCredentials = true)
    .Build();

现在看来我需要传递一个基于this Microsoft page about Auth and SignalR 的访问令牌,但是

hubConnection = new HubConnectionBuilder()
    .WithUrl(
            NavigationManager.ToAbsoluteUri("/chathub"), options =>
            {
                options.AccessTokenProvider = () => Task.FromResult(_myAccessToken);
            })
    .Build();

这是我在 Startup 中所做的,以使 B2C 基于 Carl Franklin YouTube video 工作

//****Azure B2C****//
        services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
                .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAdB2C"));
        

        services.AddControllersWithViews()
                .AddMicrosoftIdentityUI();

        services.AddAuthorization(options =>
        {
            // By default, all incoming requests will be authorized according to the default policy
            options.FallbackPolicy = options.DefaultPolicy;
        });

        services.AddRazorPages();
        services.AddServerSideBlazor()
                .AddMicrosoftIdentityConsentHandler();

【问题讨论】:

  • 我是第一个尝试将 Azure AD B2C 与 Signalr 和 Blazor Server 结合使用的人吗?我是唯一一个疯狂或愚蠢到可以尝试这个的人吗?我想至少会有人对此有话要说。
  • 我是第二个尝试过这个的人,我得到了同样的错误。你解决了吗?
  • @user2205904 抱歉,没有。我的意思是是的,我让它工作了,但是通过删除信号 r 部分的身份验证。在简单地放弃之前,我环顾了几个星期。在我的个人爱好项目上,我的风帆已经完全消失了,从那以后我就再也没有使用过 Blazor。
  • 老兄,它即将对我做同样的事情,怎么没有在 blazor 服务器中编写的聊天应用程序不使用单例(无法将消息范围限定给用户),或者不是广播.. 让我很痛苦.
  • 这不是个人项目,不幸的是,我别无选择,只能把头撞在桌子上

标签: signalr azure-ad-b2c access-token blazor-server-side signalr-hub


【解决方案1】:

我也遇到了同样的问题,并设法让它工作。从我的组件连接时,我必须手动将身份验证 cookie 传递到集线器。

这是我的 Hub 类:

[Authorize]
    public class NotificationsHub : Microsoft.AspNetCore.SignalR.Hub
    {
        public async override Task OnConnectedAsync() {
            var user = Context.User;
            var identifier = Context.UserIdentifier;
            string name = Context.User.Claims.First(x => x.Type.Equals("name")).Value;
            await base.OnConnectedAsync();
            await Clients.Caller.SendAsync("Connected", 0);
        }
    }

然后我在 Program.cs 中配置了它

app.UseEndpoints(endpoints => {
    endpoints.MapControllers();
    endpoints.MapBlazorHub();
    endpoints.MapHub<NotificationsHub>("/notificationshub");
    endpoints.MapFallbackToPage("/_Host");
});

我还将 Hub 配置为使用我的 Microsoft cookie 中的 UserId:

services.AddSingleton<IUserIdProvider, SignalRUserIdProvider>();
public class SignalRUserIdProvider : IUserIdProvider
    {
        public virtual string GetUserId(HubConnectionContext connection) {
            return connection.User?.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value!;
        }
    }

最后,我在连接到集线器时通过了 cookie。示例组件:

@using Microsoft.AspNetCore.SignalR.Client
@using Microsoft.Extensions.Configuration
@implements IAsyncDisposable
@inject IHttpContextAccessor HttpContextAccessor;
@inject NavigationManager Navigate;

@code {
    private HubConnection hubConnection;

    protected override async Task OnInitializedAsync() {
        hubConnection = new HubConnectionBuilder()
            .WithUrl(Navigate.ToAbsoluteUri("/notificationshub"), options => {
                if (HttpContextAccessor.HttpContext != null) {
                    foreach (var cookie in HttpContextAccessor.HttpContext.Request.Cookies) {
                        // IF THE DOMAIN PARAMETER IS WRONG YOU WILL RECEIVE THE JSON ERROR.
                        options.Cookies.Add(new Cookie(cookie.Key, cookie.Value, null, domain: "localhost"));
                    }
                }
            })
            .WithAutomaticReconnect()
            .Build();

        hubConnection.On<int>("Connected", i => {
            // Yay, it worked
            StateHasChanged();
        });

        await hubConnection.StartAsync();
    }

    public async ValueTask DisposeAsync() {
        if (hubConnection is not null) {
            await hubConnection.DisposeAsync();
        }
    }
}

很久没有遇到这个问题了,如果有什么不清楚的地方请告诉我。

希望对你有帮助!

【讨论】:

  • 嘿,cookie 必须是 Azure SignalR 服务器的域还是我的 azure 应用服务的域?我使用您的代码和用户提供程序在本地工作。试图确定 HttpContext 是否为 null 或其与错误域的匹配。去查看日志
猜你喜欢
  • 2021-05-18
  • 2022-08-09
  • 1970-01-01
  • 2019-12-04
  • 1970-01-01
  • 2022-08-02
  • 2020-12-17
  • 1970-01-01
  • 2020-06-10
相关资源
最近更新 更多