首先项目中使用IdentityServer负责项目的登录认证服务。
在客户端SignalR配置如下
@inject IHttpContextAccessor httpContextAccessor
@code{
private HubConnection connection;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
if (httpContextAccessor.HttpContext.User.Identity.IsAuthenticated)
{
connection = new HubConnectionBuilder()
.WithUrl("http://localhost:4200/chat", options =>
{
if (httpContextAccessor.HttpContext != null)
{
foreach (var cookie in httpContextAccessor.HttpContext.Request.Cookies)
{
options.Cookies.Add(new Cookie(cookie.Key, cookie.Value, null, "localhost"));
}
}
})
.Build();
connection.Closed += async (error) =>
{
await Task.Delay(new Random().Next(0, 5) * 1000);
await connection.StartAsync();
};
try
{
await connection.StartAsync();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
在这里说明一下,对连接到中心 SignalR 的用户进行身份验证有多种方式,具体可以看官方文档 https://docs.microsoft.com/zh-cn/aspnet/core/signalr/authn-and-authz?view=aspnetcore-3.1
这里我们使用的是Cookies方式,因为在Blazor应用中,我们使用的是SignalR .Net客户端,请求并非来自浏览器。如果使用的是js的客户端,使用持有者令牌身份验证应该是没问题的。
之前一直试图使用令牌验证,但是始终获取不到身份信息,这里文档里并没有交代,感觉是个小坑希望大家可以避免遇到
Cookie身份验证
在基于浏览器的应用中 cookie ,身份验证允许现有用户凭据自动流向 SignalR 连接。 使用浏览器客户端时,无需其他配置。 如果用户登录到应用,则连接 SignalR 会自动继承此身份验证。
Cookie是一种特定于浏览器的发送访问令牌的方法,但非浏览器客户端可以发送这些令牌。 使用 .NET 客户端时,可以在调用中配置 属性 Cookies .WithUrl 以提供 cookie 。 但是, cookie 从 .NET 客户端使用身份验证需要应用提供 API 来交换 的身份验证数据 cookie 。
持有者令牌身份验证
客户端可以提供访问令牌,而不是使用 cookie 。 服务器验证令牌并使用它来标识用户。 此验证仅在建立连接时完成。 在连接期间,服务器不会自动重新验证以检查令牌吊销。