【问题标题】:Blazor Server Signalr hub is missing user claimsBlazor Server Signalr 集线器缺少用户声明
【发布时间】:2021-05-18 18:32:54
【问题描述】:

我已经花了一个多月的时间解决了这个问题。

目标是在 Blazor 服务器应用的 Signalr 中心中获取用户声明。我在我的 Github 上上传了一个非常简单的应用程序。客户端可以通过单击按钮调用集线器上的方法,集线器方法发送回一条带有 User.Identity.Name 的消息。但是,由于用户声明为空,我无法获取名称。

这里是存储库: https://github.com/aadurham/blazorserverauth

很多人在这里和其他地方都在问同样的问题。信息/建议/解决方案分散。事实证明,对我(可能对我的编程水平的任何人来说)将这些部分组合在一起并使其工作是不可能的。

我怀疑一个优秀的程序员在上面的简单应用程序中将各个部分组合在一起不会花费太多时间。我相信很多人,包括我自己,都会从中受益。我希望有好心人能伸出援手。在这种情况下,请提出拉取请求。我会将代码保留在那里以供其他人使用,并将尝试稍后添加手册。我还会回来尝试使用类似简单的 Blazor WASM 应用程序来做同样的事情。

在此先感谢

【问题讨论】:

标签: authentication signalr blazor claims


【解决方案1】:

来自这个回购https://github.com/BrianLParker/SignalRAuth

    protected override async Task OnInitializedAsync()
    {

        hubConnection = new HubConnectionBuilder()
            .WithUrl(NavigationManager.ToAbsoluteUri("/chathub"), options =>
            {
                options.AccessTokenProvider = async () =>
                {
                    var accessTokenResult = await AccessTokenProvider.RequestAccessToken();
                    accessTokenResult.TryGetToken(out var accessToken);
                    return accessToken.Value;
                };
            })
            .Build();

        hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
        {
            var encodedMsg = $"{user}: {message}";
            messages.Add(encodedMsg);
            StateHasChanged();
        });

        await hubConnection.StartAsync();
    }

[Authorize]
public class ChatHub : Hub
{
    private readonly UserManager<ApplicationUser> userManager;

    public ChatHub(UserManager<ApplicationUser> userManager)
    {
        this.userManager = userManager;
    }

    public async Task SendMessage(string user, string message)
    {
        var userId = Context.UserIdentifier;
        var applicationUser = await userManager.FindByIdAsync(userId);

        await Clients.All.SendAsync("ReceiveMessage", applicationUser.Email, message);
    }
}

【讨论】:

  • 非常感谢布赖恩。我已经下载了你的代码,会处理它。您的解决方案似乎适用于 WASM,我无法使其适用于上面的 Blazor 服务器应用程序。不过我会继续努力的。谢谢。
  • @aadurham 很抱歉我错过了。创建hubconnection 的选项是关键。
  • 还是很有帮助的,我也一直在计划为 wasm 发布另一个问题,因为有很多人在问这个问题。很高兴您也发布了回购协议,谢谢!
  • 谢谢,我想我已经解决了这个问题。不完美,但有效。我在下面解释它。根本不需要处理令牌,只需将您喜欢的任何内容添加到连接的标题中即可。再次感谢,您的解决方案将在 WASM 中派上用场。
【解决方案2】:

我想出了一个简单的解决方案,虽然不完美但很好。我的目标是将一些用户信息传递给集线器,以便我可以使用 userid(或任何喜欢的用户信息)注册 connectionid。迄今为止我未能实施的可用解决方案建议在连接时添加令牌。相反,我将用户信息添加到标题并在集线器上提取它,如下所示:

这是客户端代码:

@code{
    [CascadingParameter]
    private Task<AuthenticationState> _authstate { get; set; }


    private HubConnection connection;
    private AuthenticationState authstate { get; set; }
    private List<string> messages = new List<string>();



    protected override async Task OnInitializedAsync()
    {
        authstate = await _authstate;

        if (authstate != null)
        {
            var userid = authstate.User.Identity.Name;

            connection = new HubConnectionBuilder()
                .WithUrl(NavigationManager.ToAbsoluteUri("/myhub"), options => {
                    options.Headers.Add("USERID", userid);
                })
                .WithAutomaticReconnect()
                .Build();



            connection.On<string, string>("ReceiveMessage", ReceiveMessage);

            await connection.StartAsync();
        }
    }


    public void ReceiveMessage(string user, string msg)
    {
        messages.Add(user + " " + msg);
        StateHasChanged();
    }

    public async void InvokeSomething()
    {
        await connection.InvokeAsync("InvokeSomething");
    }
}

这是我在集线器上提取用户信息的方式:

public async Task InvokeSomething()
{
    var httpCtx = Context.GetHttpContext();
    var name = httpCtx.Request.Headers["USERID"].ToString();
    await Clients.All.SendAsync("ReceiveMessage", name, " invoked this");
}`

它有效。在 OnConnectedAsync 中也使用相同的方法。

希望这对某人有所帮助。 github repo 中的更新代码。

集线器上的 Authorize 属性使应用程序崩溃。所以我认为与集线器的连接没有经过身份验证(微软文档声称我们不需要做任何其他事情)。我希望比我有更好技能的人提供更好的解决方案。与此同时,这似乎正在发挥作用。

更新

找到解决方案 为了启用 Hub 类的授权,必须将用户通过身份验证时创建的安全 cookie 传递给 Blazor Server SPA 应用。您应该在创建集线器连接时传递 cookie。这将允许您通过 Context 对象在 Hub 中访问所有声明,例如 UserIdentofier 和 UserName。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 1970-01-01
    • 2012-10-04
    • 2013-07-11
    相关资源
    最近更新 更多