我创建了一个Blazor服务器应用程序,试图开始学习Blazor和一些新技术。我遵循了微软的中心聊天教程。事情进展顺利。然后我添加了一些基本的cookie身份验证,事情仍然在不断发展。然后,我在Blazor Train上学习了Carl Franklin关于将应用程序连接到Azure AD B2C的教程。除了应用程序的聊天中心部分,它还能工作。该应用程序的所有其他部分都运行良好,并显示用户的信息。
我几乎可以肯定的是,"hubconnection"
之所以失败,是因为它没有进行身份验证,因为它没有获得访问令牌。故障发生在await hubConnection.StartAsync();
线上,错误为System.Text.Json.JsonReaderException: '<' is an invalid start of a value
。我很确定HTML会返回403消息或类似的内容。
所以我想我有两个问题:
-
如何查看导致
HubConnectionBuilder
出错的value
?即使我设置了断点,我也永远看不到导致它阻塞的值是什么。 -
如何将访问令牌传递给HubConnectionBuilder?
我发现了很多";"方式";做这件事要么已经过时,要么我无法工作:
使用已弃用的 AddAzureADB2CBearer
将参数传递到应用程序,我无法使用
适用于Azure AD,而非B2C
这就是使用Cookie auth:的原因
hubConnection = new HubConnectionBuilder()
.WithUrl(
NavigationManager.ToAbsoluteUri("/chathub"),
config => config.UseDefaultCredentials = true)
.Build();
现在,我似乎需要在这个关于Auth和SignalR但的Microsoft页面上传递一个访问令牌
hubConnection = new HubConnectionBuilder()
.WithUrl(
NavigationManager.ToAbsoluteUri("/chathub"), options =>
{
options.AccessTokenProvider = () => Task.FromResult(_myAccessToken);
})
.Build();
以下是我在Startup中所做的基于Carl Franklin YouTube视频的B2C工作
//****Azure B2C****//
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAdB2C"));
services.AddControllersWithViews()
.AddMicrosoftIdentityUI();
services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the default policy
options.FallbackPolicy = options.DefaultPolicy;
});
services.AddRazorPages();
services.AddServerSideBlazor()
.AddMicrosoftIdentityConsentHandler();
我也遇到了同样的问题,并设法使其正常工作。从组件连接时,我必须手动将身份验证cookie传递到集线器。
这是我的集线器类:
[Authorize]
public class NotificationsHub : Microsoft.AspNetCore.SignalR.Hub
{
public async override Task OnConnectedAsync() {
var user = Context.User;
var identifier = Context.UserIdentifier;
string name = Context.User.Claims.First(x => x.Type.Equals("name")).Value;
await base.OnConnectedAsync();
await Clients.Caller.SendAsync("Connected", 0);
}
}
然后我在Program.cs 中配置了它
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapHub<NotificationsHub>("/notificationshub");
endpoints.MapFallbackToPage("/_Host");
});
我还将集线器配置为使用我的Microsoft cookie中的UserId:
services.AddSingleton<IUserIdProvider, SignalRUserIdProvider>();
public class SignalRUserIdProvider : IUserIdProvider
{
public virtual string GetUserId(HubConnectionContext connection) {
return connection.User?.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value!;
}
}
最后,我在连接到我的集线器时通过了cookie。示例组件:
@using Microsoft.AspNetCore.SignalR.Client
@using Microsoft.Extensions.Configuration
@implements IAsyncDisposable
@inject IHttpContextAccessor HttpContextAccessor;
@inject NavigationManager Navigate;
@code {
private HubConnection hubConnection;
protected override async Task OnInitializedAsync() {
hubConnection = new HubConnectionBuilder()
.WithUrl(Navigate.ToAbsoluteUri("/notificationshub"), options => {
if (HttpContextAccessor.HttpContext != null) {
foreach (var cookie in HttpContextAccessor.HttpContext.Request.Cookies) {
// IF THE DOMAIN PARAMETER IS WRONG YOU WILL RECEIVE THE JSON ERROR.
options.Cookies.Add(new Cookie(cookie.Key, cookie.Value, null, domain: "localhost"));
}
}
})
.WithAutomaticReconnect()
.Build();
hubConnection.On<int>("Connected", i => {
// Yay, it worked
StateHasChanged();
});
await hubConnection.StartAsync();
}
public async ValueTask DisposeAsync() {
if (hubConnection is not null) {
await hubConnection.DisposeAsync();
}
}
}
我已经很久没有遇到这个问题了,所以如果有什么不清楚的地方,请告诉我。
希望它能有所帮助!