Blazor WebAssembly SignalR Authentication



我很想看到一个示例,说明如何使用 Blazor 的 WebAssembly 风格向 SignalR 中心连接添加身份验证。我的 dotnet 版本是 3.1.300。

我可以按照以下步骤使打开的、未经身份验证的 SignalR 连接正常工作:https://learn.microsoft.com/en-us/aspnet/core/tutorials/signalr-blazor-webassembly?view=aspnetcore-3.1&tabs=visual-studio

我发现的所有教程似乎都较旧,或者适用于服务器托管类型,并且不使用内置模板。

我已使用适当的模板和以下说明(包括数据库(将身份验证添加到后端的其余部分: https://learn.microsoft.com/en-us/aspnet/core/security/blazor/?view=aspnetcore-3.1

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

那里有各种各样的半解决方案,或者为旧版本设计的,但没有任何东西可以建立在 MS 提供的库存教程之上。

更新: 按照此新闻稿 https://devblogs.microsoft.com/aspnet/blazor-webassembly-3-2-0-preview-2-release-now-available/中的提示,我现在可以从 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: 我在这里尝试了提示:https://github.com/dotnet/aspnetcore/issues/18697

并将我的代码更改为:

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

但没有快乐。

我遇到了同样的问题。

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

布莱泽

在连接生成器中,应添加访问令牌提供程序:

string accessToken = "eyYourToken";
connection = new HubConnectionBuilder()
.WithUrl("https://localhost:5001/hub/chat", options =>
{
options.AccessTokenProvider = () => Task.FromResult(token.Value);
})
.Build();

options.AccessTokenProvider属于Func<Task<string>>类型,因此您也可以在此处执行异步操作。如果需要的话。

仅执行此操作,应该允许 SignalR 工作。

后端

然而!当 SignalR 尝试创建 WebSocket 连接时,可能仍会看到错误。这是因为您可能在后端使用 IdentityServer,并且不支持来自查询字符串的 Jwt 令牌。不幸的是,SignalR 尝试通过名为access_token的查询字符串参数授权 websocket 请求。

将此代码添加到您的启动:

.AddJwtBearer("Bearer", options =>
{
// other configurations omitted for brevity
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
// If the request is for our hub...
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/hubs"))) // Ensure that this path is the same as yours!
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});

编辑 1:阐明了 Blazor SignalR 代码的用法

就我而言(Blazor WebAssembly,使用 JWT 持有者令牌身份验证托管在 ASP.NET Core 5.0 上(,我必须添加以下内容:

Blazor WASM 客户端

构建连接时(在我的例子中:在某些服务代理类的构造函数中(,请使用IAccessTokenProvider并配置AccessTokenProvider选项,如下所示:

public ServiceProxy(HttpClient httpClient, IAccessTokenProvider tokenProvider) {
HubConnection = new HubConnectionBuilder()
.WithUrl(
new Uri(httpClient.BaseAddress, "/hubs/service"),
options => {
options.AccessTokenProvider = async () => {
var result = await tokenProvider.RequestAccessToken();
if (result.TryGetToken(out var token)) {
return token.Value;
}
else {
return string.Empty;
}
};
})
.WithAutomaticReconnect() // optional
.Build();
}

ASP.NET 核心服务器

将以下内容添加到Startup.ConfigureServices

services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options => {
// store user's "name" claim in User.Identity.Name
options.TokenValidationParameters.NameClaimType = "name";
// pass JWT bearer token to SignalR connection context
// (from https://learn.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-5.0)
options.Events = new JwtBearerEvents {
OnMessageReceived = context => {
var accessToken = context.Request.Query["access_token"];
// If the request is for on of our SignalR hubs ...
if (!string.IsNullOrEmpty(accessToken) &&
(context.HttpContext.Request.Path.StartsWithSegments("/hubs/service"))) {
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});

这是我的解决方案,有效

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

相关内容

  • 没有找到相关文章

最新更新