【发布时间】:2022-01-26 00:18:18
【问题描述】:
我正在开发一个 blazor Web 程序集应用程序,我想使用 SignalR 发送推送通知。我可以建立连接并向所有用户发送通知,但我遇到了问题。我想在用户连接到应用程序时存储用户信息。在 OnConnected 方法中,我可以访问 ConnectionId 但 UserIdentifier 为空。我关注这个link。但什么也没发生,它仍然为空。
此代码在客户端建立连接:
public async Task<bool> ConnectToNotificationHub()
{
bool isConnected = false;
string url = $"{_configuration["APIBaseURL"]}/hubs/notificationhub";
string token = await _localStorageService.GetItemAsStringAsync("user_account");
if (!string.IsNullOrEmpty(token))
{
HubConnection hubConnection = new HubConnectionBuilder()
.WithUrl(url, options =>
{
options.AccessTokenProvider=() => Task.FromResult(token);
})
.Build();
await hubConnection.StartAsync();
isConnected=true;
hubConnection.Closed+=async (s) =>
{
isConnected=false;
await hubConnection.StartAsync();
isConnected=true;
};
hubConnection.On<string>("notification", m =>
{
_notifications.Add(m);
OnNotificationRecieved(null, null);
});
}
return isConnected;
}
这是 api 项目中的 Configure 方法:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors("PMS_API");
app.UseMiddleware<CustomExceptionHandlerMiddleware>();
if (env.IsDevelopment())
{
//app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "PMS.WebAPI v1"));
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<NotificationHub>("/hubs/notificationhub");
endpoints.MapControllers();
});
}
这是我的中心:
public class NotificationHub : Hub
{
[Authorize]
public override Task OnConnectedAsync()
{
Debug.WriteLine($"ConnectionId: {Context.ConnectionId} - UserIdentifier: {Context.UserIdentifier}"); // TODO: UserIdentifier is empty
return base.OnConnectedAsync();
}
}
这是身份事件:
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")))
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
if (context.Exception != null)
{
throw new AppException(HttpStatusCode.Unauthorized, "Autentication failed.", context.Exception);
}
return Task.CompletedTask;
},
OnChallenge = context =>
{
if (context.AuthenticateFailure != null)
{
throw new AppException(HttpStatusCode.Unauthorized, "Autentication failed.", context.AuthenticateFailure);
}
throw new AppException(HttpStatusCode.Unauthorized, "You are unauthorized to access this resource.", null);
},
OnTokenValidated = async context =>
{
var claimsIdentity = context.Principal.Identity as ClaimsIdentity;
var signInManager = context.HttpContext.RequestServices.GetRequiredService<SignInManager<User>>();
var userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<User>>();
if (!claimsIdentity.Claims.Any())
{
context.Fail("No claims were found.");
}
var securityStampClaim = claimsIdentity.FindFirst(new ClaimsIdentityOptions().SecurityStampClaimType);
if (securityStampClaim is null)
{
context.Fail("No security stamp was found.");
}
var validatedSecurityStamp = await signInManager.ValidateSecurityStampAsync(context.Principal);
if (validatedSecurityStamp is null)
{
context.Fail("Security stamp is not valid.");
}
var userIdClaim = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier);
if (userIdClaim is null)
{
context.Fail("User id claim was not found.");
}
var userId = userIdClaim.Value;
var user = await userManager.FindByIdAsync(userId);
if (user.LastCreatedToken is null)
{
context.Fail("User not logged in.");
}
if (user.LastTokenExpireDate is not null && user.LastTokenExpireDate < DateTime.Now)
{
context.Fail("User last token has expired.");
}
if (!user.IsActive)
{
context.Fail("User is not active.");
}
user.LastLoginDate = DateTime.Now;
await userManager.UpdateAsync(user);
}
};
你能帮帮我吗?
谢谢
【问题讨论】:
-
将
[Authorize]放在集线器类而不是 OnConnectedAsync 方法上 -
@Brennan 我更改了 [Authorize] 属性的位置,但是现在当我尝试建立连接时,api 应用程序停止并在 OnChallenge 事件中引发异常。我在问题中添加了身份事件。
-
谢谢@Brennan,我找到了问题。
标签: c# asp.net-core signalr asp.net-core-webapi blazor-webassembly