Authentication Blazor WebAssembly信号器身份验证

Authentication Blazor WebAssembly信号器身份验证,authentication,signalr,blazor,webassembly,Authentication,Signalr,Blazor,Webassembly,我希望看到一个关于如何使用Blazor的WebAssembly风格向SignalR hub连接添加身份验证的示例。我的dotnet版本是3.1.300 我可以按照以下步骤使未经验证的开放信号机连接正常工作: 我发现的所有教程似乎都比较旧,或者是针对服务器托管类型的,并且没有使用内置模板 我已使用适当的模板和以下说明(包括数据库)将身份验证添加到后端的其余部分: 但每次我将[Authenticate]添加到聊天中心时,都会返回一个错误。扩展第一个教程,我们是否可以验证在那里创建的集线器?挂接到内

我希望看到一个关于如何使用Blazor的WebAssembly风格向SignalR hub连接添加身份验证的示例。我的dotnet版本是3.1.300

我可以按照以下步骤使未经验证的开放信号机连接正常工作:

我发现的所有教程似乎都比较旧,或者是针对服务器托管类型的,并且没有使用内置模板

我已使用适当的模板和以下说明(包括数据库)将身份验证添加到后端的其余部分:

但每次我将[Authenticate]添加到聊天中心时,都会返回一个错误。扩展第一个教程,我们是否可以验证在那里创建的集线器?挂接到内置ASP.NET系统会很好,但我可以将令牌作为附加参数传入,然后自己做,如果这样做最好的话。在这种情况下,我需要学习如何从Blazor WebAssembly中获取令牌,然后在服务器上的某个地方查找它。这似乎是错误的,但它基本上可以满足我的需要,作为替代

现在有各种各样的半解决方案,或者是为旧版本设计的,但是没有任何东西是建立在微软提供的股票教程之上的

更新: 按照本新闻稿中的提示,我现在可以从razor页面中获取一个令牌,并将其注入到标题中。我想这很好??但是,我如何获取它并在服务器上使用它呢

以下是razor代码的一个片段:

protected override async Task OnInitializedAsync()
{
    var httpClient = new HttpClient();
    httpClient.BaseAddress = new Uri(UriHelper.BaseUri);

    var tokenResult = await AuthenticationService.RequestAccessToken();

    if (tokenResult.TryGetToken(out var token))
    {
        httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.Value}");

        hubConnection = new HubConnectionBuilder()
            .WithUrl(UriHelper.ToAbsoluteUri("/chatHub"), options =>
            {
                options.AccessTokenProvider = () => Task.FromResult(token.Value);
            })
            .Build();
    }
}
更新2: 我试过这里的提示:

并将我的代码更改为:

        hubConnection = new HubConnectionBuilder()
            .WithUrl(NavigationManager.ToAbsoluteUri("/chatHub?access_token=" + token.Value))
            .Build();

但是没有乐趣。

这是我的解决方案,很有效

[Inject] HttpClient httpClient { get; set; }
[Inject] IAccessTokenProvider tokenProvider { get; set; }
HubConnection hubConnection { get; set; }

(...)

private async Task ConnectToNotificationHub()
{
    string url = httpClient.BaseAddress.ToString() + "notificationhub";

    var tokenResult = await tokenProvider.RequestAccessToken();

    if (tokenResult.TryGetToken(out var token))
    {
        hubConnection = new HubConnectionBuilder().WithUrl(url, options =>
        {
            options.Headers.Add("Authorization", $"Bearer {token.Value}");
        }).Build();


        await hubConnection.StartAsync();

        hubConnection.Closed += async (s) =>
        {
            await hubConnection.StartAsync();
        };

        hubConnection.On<string>("notification", m =>
        {
            string msg = m;
        });
    }
}
[Inject]HttpClient HttpClient{get;set;}
[Inject]IAccessTokenProvider tokenProvider{get;set;}
HubConnection HubConnection{get;set;}
(...)
专用异步任务ConnectToNotificationHub()
{
字符串url=httpClient.BaseAddress.ToString()+“notificationhub”;
var tokenResult=wait tokenProvider.RequestAccessToken();
if(tokenResult.TryGetToken(out-var-token))
{
hubConnection=新建HubConnectionBuilder()。带有url(url,选项=>
{
options.Headers.Add(“Authorization”、$“Bearer{token.Value}”);
}).Build();
等待hubConnection.StartAsync();
hubConnection.Closed+=异步=>
{
等待hubConnection.StartAsync();
};
hubConnection.On(“通知”,m=>
{
字符串msg=m;
});
}
}

我遇到了同样的问题

我的解决方案是双面的:我必须在前端和后端修复一些东西

布拉佐 在连接生成器中,应添加AccessTokenProvider:

string accessToken=“eyYourToken”;
连接=新的HubConnectionBuilder()
.WithUrl(“https://localhost:5001/hub/chat,选项=>
{
options.AccessTokenProvider=()=>Task.FromResult(token.Value);
})
.Build();
options.AccessTokenProvider
属于
Func
类型,因此您也可以在此处执行异步操作。如果需要的话

仅这样做,应允许信号器工作

后端 然而当信号器尝试创建WebSocket连接时,您可能仍然会看到错误。这是因为您可能在后端使用IdentityServer,而这不支持查询字符串中的Jwt标记。不幸的是,信号器试图通过名为
access\u token
的查询字符串参数来授权websocket请求

将此代码添加到启动中:

.AddJwtBearer(“Bearer”,选项=>
{
//为简洁起见,省略了其他配置
options.Events=newjwtbearerevents
{
OnMessageReceived=上下文=>
{
var accessToken=context.Request.Query[“访问令牌”];
//如果请求是针对我们的中心。。。
var path=context.HttpContext.Request.path;
如果(!string.IsNullOrEmpty(accessToken)&&
(path.StartsWithSegments(“/hubs”)//确保此路径与您的路径相同!
{
//从查询字符串中读取令牌
context.Token=accessToken;
}
返回Task.CompletedTask;
}
};
});
编辑1:澄清了Blazor信号器代码的用法在我的案例中(Blazor WebAssembly,使用JWT承载令牌Auth托管在ASP.NET Core 5.0上),我必须添加以下内容:

Blazor WASM客户端 在构建连接时(在我的示例中:在某个服务代理类的构造函数中),使用
IAccessTokenProvider
并配置
AccessTokenProvider
选项,如下所示:

public ServiceProxy(HttpClient-HttpClient,IAccessTokenProvider-tokenProvider){
HubConnection=新的HubConnectionBuilder()
.WithUrl(
新Uri(httpClient.BaseAddress,“/hubs/service”),
选项=>{
options.AccessTokenProvider=async()=>{
var result=wait tokenProvider.RequestAccessToken();
if(result.TryGetToken(out-var-token)){
返回token.Value;
}
否则{
返回字符串。空;
}
};
})
.WithAutomaticReconnect()//可选
.Build();
}
ASP.NET核心服务器 将以下内容添加到启动。配置服务:

services.Configure(JwtBearerDefaults.AuthenticationScheme,选项=>{
//在user.Identity.name中存储用户的“name”声明
options.TokenValidationParameters.NameClaimType=“name”;
//将JWT承载令牌传递给信号器连接上下文
//(来自https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-5.0)
options.Events=newjwtbearerevents{
OnMessageReceived=上下文=>{
var accessToken=context.Request.Query[“访问”