【发布时间】:2021-11-07 18:07:37
【问题描述】:
我有一个使用 OpenId 进行身份验证的应用程序。启动中的代码是:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = new PathString("/account/login");
})
.AddOpenIdConnect("CustomScheme", options =>
{
// options configured
});
我有一个集线器,并在app.UseEndpoints 中连接集线器,如下所示:
endpoints.MapHub<SpecialMessageHub>("myspecialhub");
除了发布我的整个 Startup.cs 文件之外,这里是一个快速概述:
-
app.UseAuthentication();和app.UseAuthorization();在app.UseEndpoints之前 -
services.AddSignalR();和services.AddServerSideBlazor();在services.AddAuthentication和services.AddAuthorization之后
我已经为这个问题简化了我的 Hub:
using Example.Extensions;
using Example.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using System.Threading;
using System.Threading.Tasks;
namespace Example.Hubs
{
[Authorize]
public class SpecialMessageHub : Hub
{
public override Task OnConnectedAsync()
{
var customerId = Context.User.GetCustomerId();
Groups.AddToGroupAsync(Context.ConnectionId, GetCustomerGroupName(customerId));
return base.OnConnectedAsync();
}
public Task SendMessage(string customerId,
SpecialMessage message,
CancellationToken cancellationToken)
{
return Clients.Groups(GetCustomerGroupName(customerId)).SendAsync("ReceiveMessage", message, cancellationToken);
}
public static string GetCustomerGroupName(string customerId) => $"customers-{customerId}";
}
}
**注意:GetCustomerId 是我项目中的扩展方法
我有一个简单的组件来测试这个:
@page "/"
@using Microsoft.AspNetCore.SignalR.Client
@using Example.Models
@inject Microsoft.AspNetCore.Components.NavigationManager NavigationManager
@implements IAsyncDisposable
<h2>@myMessage.Id</h2>
<div>@myMessage.Message</div>
@code {
private HubConnection hubConnection;
private SpecialMessage myMessage = new SpecialMessage();
protected override async Task OnInitializedAsync()
{
if (!IsConnected)
{
hubConnection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri("/myspecialhub"))
.WithAutomaticReconnect()
.Build();
hubConnection.On<string, SpecialMessage>
("ReceiveMessage", (user, message) =>
{
myMessage = message;
StateHasChanged();
});
await hubConnection.StartAsync().ConfigureAwait(false);
}
}
public bool IsConnected => hubConnection != null
&& hubConnection.State == HubConnectionState.Connected;
public async ValueTask DisposeAsync()
{
await hubConnection?.DisposeAsync();
}
}
然后我使用以下内容将该组件添加到我的视图中:
<component type="typeof(SpecialMessageComponent)" render-mode="ServerPrerendered"/>
当我点击这个视图时,它返回一个 401:
基于这个https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-3.1,cookie应该被传递到集线器:
在基于浏览器的应用程序中,cookie 身份验证允许您现有的 用户凭据自动流向 SignalR 连接。什么时候 使用浏览器客户端,无需额外配置。如果 用户登录到您的应用,SignalR 连接 自动继承此身份验证。
我能够验证用户是否已通过身份验证,并且在控制器和组件中都有我正在寻找的声明。我觉得这应该相当简单,不需要多次跳跃,因此非常感谢任何帮助。
以下是我尝试过的一些事情:
-
从视图中的上下文中拉出“access_token”和“id_token”,并将其作为参数传递给组件。然后基于这里https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-3.1#bearer-token-authentication,我做了这样的事情,但这仍然导致了401:
[Parameter] public string AccessToken { get; set; } protected override async Task OnInitializedAsync() { if (!IsConnected) { hubConnection = new HubConnectionBuilder() .WithUrl(NavigationManager.ToAbsoluteUri("/myspecialhub"), options => { options.AccessTokenProvider = () => Task.FromResult(AccessToken); }) .WithAutomaticReconnect() .Build(); hubConnection.On<string, SpecialMessage> ("ReceiveMessage", (user, message) => { myMessage = message; StateHasChanged(); }); await hubConnection.StartAsync().ConfigureAwait(false); } } } -
我试图通过将
ClaimsPrincipal替换为新的IIdentity并将AuthenticationType设置为CookieAuthenticationDefaults.AuthenticationScheme来操纵用户。这导致了一个令人讨厌的无限循环,但在重新启动应用程序后,身份被交换,但是,我仍然收到 401。 -
我也尝试过其他选项,但我似乎无法让它与 OpenId 一起使用。
【问题讨论】:
标签: c# asp.net-core signalr signalr-hub