由于 Azure ADB2C,Blazor 服务器 SignalR 集线器在 StartAsync 上失败

2024-05-14

我创建了一个 Blazor 服务器应用程序,以开始学习 Blazor 和一些更新的技术。我遵循了 Microsoft 提供的集线器聊天教程。事情进展顺利。然后我添加了一些基本的 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 消息或类似的消息。

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

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

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

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

使用已弃用的 AddAzureADB2CBearer https://stackoverflow.com/questions/61856216/how-to-use-azure-ad-b2c-with-xamarin-forms-and-signalr-core

将参数传递给我无法工作的应用程序 https://stackoverflow.com/questions/59538318/how-to-use-the-httpcontext-object-in-server-side-blazor-to-retrieve-information/59538319#59538319

适用于 Azure AD,不适用于 B2C https://github.com/javiercn/blazor-server-aad-sample

这是 Cookie 身份验证的工作原理:

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

现在看来我需要传递一个基于以下的访问令牌这个关于 Auth 和 SignalR 的 Microsoft 页面 https://learn.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-5.0 but

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

以下是我在 Startup 中所做的,以使 B2C 工作基于

//****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();

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

这是我的中心类:

[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");
});

我还将集线器配置为使用我的 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!;
        }
    }

最后,我在连接到我的 Hub 时传递了 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();
        }
    }
}

我已经很久没有遇到这个问题了,所以如果有任何不清楚的地方请告诉我。

希望能帮助到你!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

由于 Azure ADB2C,Blazor 服务器 SignalR 集线器在 StartAsync 上失败 的相关文章

随机推荐

  • 将变量声明为全局变量,然后声明为局部变量 -Shadowing-

    将变量声明为全局变量然后将其重新声明为局部变量意味着什么 int a 0 int main int a 7 return 0 我在参考文献中看到了这个例子 但我不明白 请考虑到我是 C 编程的初学者 这意味着在你的main方法 如果你只使用
  • 如何将类型传递给方法?

    我怎样才能调用这个构造函数 public class DataField public String Name public Type TheType public DataField string name Type T Name nam
  • 将 Node.js(用于实时通知)添加到现有 PHP 应用程序

    我有一个现有的 PHP 应用程序 我需要向其中添加实时通知 为了实现这一点 我安装了node js 打算添加socket io以实现所有实时功能 然而 尽管在过去的三个小时里研究并试图弄清楚如何将两者结合起来 但我发现自己并没有更接近于获得
  • Windows平台下C语言控制串口DTR和RTS引脚

    如何在windows平台上控制串口的DTR和RTS引脚 我希望通过升高或降低电压来对其进行位敲击或操作 您需要使用EscapeComm 函数 https learn microsoft com en us windows desktop a
  • Ruby on Rails - 设计注册链接不起作用 - 未定义方法“user_registration_path”

    这个问题之前已经报告过 但我仍然无法找到解决方案 我已将插件 Devise 安装到我的新 RoR 项目中 当我点击注册链接时 我被重定向到以下路线 http localhost 3000 users registration sign up
  • 如何在css3中制作曲线风格的菜单?

    是否可以用css3制作曲线 圆弧样式的菜单 我可以使用canvas或HTML5中的其他东西来实现这一点吗 预先感谢 洛根 不幸的是 我不知道有什么优雅的解决方案 特别是当涉及到菜单项时 但弧线本身应该可以在纯 css 和几个 html 元素
  • 2^31 次方的 Java 指数错误 [重复]

    这个问题在这里已经有答案了 我正在编写一个java程序来输出2的指数幂 顺便说一句 我不能使用Math pow 但是在 2 31 和 2 32 处我得到了其他东西 另外 我不打算接受负整数 My code class PrintPowers
  • React Native TypeError:无法读取未定义的属性“createClient”

    我是 React 本机框架的新手 我使用 create react native app AwesomeProject 创建了应用程序 我想在我的项目中使用 BLE 因此我安装了 react native ble plx 模块 但是当我创建
  • 无法验证 GitHub 中的虚假电子邮件

    我已经创建了一个 GitHub 帐户 并且我不喜欢公开分享我的电子邮件地址 我厌倦了垃圾邮件 所以我关注了 GitHub保密您的电子邮件地址 https help github com articles keeping your email
  • 向 ReduxReducer 添加回调

    是否有任何错误 反模式 就 React Redux 中的思考 中添加了一个回调action data转化为行动 reducer ACTION FOR REDUCER var x 123 if action data callback act
  • 如何使用 Angular 2 动画实现翻转效果?

    我一直在我的项目中使用纯CSS翻转卡片 但这个解决方案不是合适的 有人可以通过点击按钮来呈现角度 2 的翻转吗 我在 angularjs 中找到了一个https codepen io Zbeyer pen oXQrZg https code
  • 从模态 MFC 表单获取输入信息

    我已经创建了表格CPreparationDlg具有Edit Control 然后我创建了创建模态表单的应用程序 在按 确定 后 我需要将编辑控件中输入的文本读入主程序的变量中 最好的方法是什么 class CPreparationApp p
  • gsutil 复制到存储失败

    我正在 us central1 a 区域的实例中工作 无法复制 200GB 文件 我试过了 gsutil m cp L my log my file gs my bucket gsutil m cp L my second log my f
  • 如何使用 TypeScript、Jest 和 Enzyme 测试 React 中的按钮点击

    我正在使用 TypeScript 构建一个 React Native 应用程序 我正在使用 Jest 和 Enzyme 进行组件测试 我也在使用 React 导航 我正在努力编写单击按钮的单元测试 这是组件的代码 只是渲染函数 render
  • 尝试注册 RCTBridgeModule 类 RCTFileReaderModule

    尝试为名称 FileReaderModule 注册 RCTBridgeModule 类 RCTFileReaderModule 但该名称已由类 FileReaderModule 注册 尝试使用命令react native run ios在i
  • 如何将 Pyspark Dataframe 标题设置到另一行?

    我有一个如下所示的数据框 col1 col2 col3 id name val 1 a01 X 2 a02 Y 我需要从中创建一个新的数据框 使用 row 1 作为新的列标题并忽略或删除 col1 col2 等行 新表应如下所示 id na
  • 如何避免这两个 SQL 语句之间出现死锁?

    我有两个存储过程在单独的线程中运行 在 SQL Server 2005 上运行 一个过程将新行插入到一组表中 另一个过程从同一组表中删除旧数据 这些过程在表上遇到了死锁DLevel and Model 这是架构 source barrams
  • URL 中的 %2C 是什么?

    在 URL 中 什么是 2C编码的含义及其用途是什么 查看http www asciitable com http www asciitable com 看着那 这Hx 十六进制 列 2C映射到 任何不寻常的编码都可以通过这种方式检查 Hx
  • 在 Android 中加密/解密字符串的简单方法

    我的问题是如何加密String String AndroidId Override public void onCreate Bundle savedInstanceState super onCreate savedInstanceSta
  • 由于 Azure ADB2C,Blazor 服务器 SignalR 集线器在 StartAsync 上失败

    我创建了一个 Blazor 服务器应用程序 以开始学习 Blazor 和一些更新的技术 我遵循了 Microsoft 提供的集线器聊天教程 事情进展顺利 然后我添加了一些基本的 cookie 身份验证 事情仍然在进展中 然后 我按照 Car