英文:
Context.User.Identity.Name is null when accessed through signalr hub
问题
I am trying to access Context.User.Identity.Name inside my signalr hub but I keep getting null.
我试图在我的 SignalR Hub 中访问 Context.User.Identity.Name,但始终返回 null。
I added [Authorize] attribute on top of the hub class, but now I am getting 401 Unauthorized error.
我在 Hub 类的顶部添加了 [Authorize] 属性,但现在出现了 401 未授权错误。
Also, I am using asp.net Identity for my authorization method and it looks like my authorization cookie is getting pass through when trying to make a connection with the signalr server, but I am still unable to get Context.User.Identity.Name to show. What did I do wrong?
此外,我正在使用 asp.net Identity 进行授权,当尝试与 SignalR 服务器建立连接时,授权 cookie 看起来已经传递过去,但我仍然无法显示 Context.User.Identity.Name。我做错了什么?
Here is my program.cs
以下是我的 program.cs
文件:
// Your program.cs content here
// 你的 program.cs 内容在这里
And here is my PaymentHub.cs
以下是我的 PaymentHub.cs
文件:
// Your PaymentHub.cs content here
// 你的 PaymentHub.cs 内容在这里
Here is how I set up my connection on the client side
以下是我在客户端设置连接的方式:
// Your client-side connection setup here
// 你的客户端连接设置在这里
I searched over the internet and tried to follow the documentation, but still no luck
我在互联网上搜索并尝试按照文档进行操作,但仍然没有成功
英文:
I am trying to access Context.User.Identity.Name inside my signalr hub but I keep getting null. I added [Authorize] attribute on top of the hub class, but now I am getting 401 Unauthorized error.
Also, I am using asp.net Identity for my authorization method and it looks like my authorization cookie is getting pass through when trying to make a connection with the signalr server, but I am still unable to get Context.User.Identity.Name to show. What did I do wrong?
Here is my program.cs
global using BagiBagiDev.Shared;
global using BagiBagiDev.Server.Services.FollowerFollowingService;
global using BagiBagiDev.Server.Services.AuthService;
global using BagiBagiDev.Server.Services.UserService;
global using BagiBagiDev.Server.Services.TransactionService;
global using BagiBagiDev.Server.Services.DonatorService;
global using BagiBagiDev.Server.Services.SocialService;
global using BagiBagiDev.Server.Services.PaymentService;
global using BagiBagiDev.Server.Models;
global using BagiBagiDev.Server.Data;
global using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.AspNetCore.Identity;
using BagiBagiDev.Server;
using Duende.IdentityServer.Services;
using BagiBagiDev.Server.Services;
using BagiBagiDev.Server.Hubs;
using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddClaimsPrincipalFactory<ApplicationClaimsPrincipalFactory>();
builder.Services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
builder.Services.AddAuthentication()
.AddCookie(options =>
{
options.Cookie.Name = "BagiBagiAuth.Cookie";
options.ExpireTimeSpan = TimeSpan.FromDays(1);
})
.AddIdentityServerJwt();
builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton<IPostConfigureOptions<JwtBearerOptions>,
ConfigureJwtBearerOptions>());
builder.Services.AddResponseCompression(opts =>
{
opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "application/octet-stream" });
});
builder.Services.AddTransient<IProfileService, ProfileService>();
builder.Services.AddScoped<IFollowerFollowingService, FollowerFollowingService>();
builder.Services.AddScoped<IAuthService, AuthService>();
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<ITransactionService, TransactionService>();
builder.Services.AddScoped<IDonatorService, DonatorService>();
builder.Services.AddScoped<ISocialService, SocialService>();
builder.Services.AddScoped<IPaymentService, PaymentService>();
builder.Services.AddSwaggerGen();
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
builder.Services.AddSingleton<IUserIdProvider, NameUserIdProvider>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
app.UseWebAssemblyDebugging();
app.UseSwagger();
app.UseSwaggerUI();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseResponseCompression();
app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapHub<PaymentHub>("/ws/payment");
});
app.MapFallbackToFile("index.html");
app.Run();
And here is my PaymentHub.cs
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
namespace BagiBagiDev.Server.Hubs
{
[Authorize]
public class PaymentHub : Hub
{
public async Task PaymentChange(string userId)
{
await Clients.All.SendAsync("Test", userId);
}
public override Task OnConnectedAsync()
{
return base.OnConnectedAsync();
}
}
}
Here is how I set up my connection on the client side
private HubConnection? hubConnection;
protected override async Task OnInitializedAsync()
{
Balance = await userService.GetUserBalance();
hubConnection = new HubConnectionBuilder()
.WithUrl(navigationManager.ToAbsoluteUri($"/ws/payment"))
.WithAutomaticReconnect()
.Build();
await hubConnection.StartAsync();
}
I searched over the internet and tried to follow the documentation, but still no luck
答案1
得分: 1
你已经设置好了客户端以发送令牌吗?
[Inject]
private AuthenticationStateProvider AuthenticationStateProvider { get; set; } = default!;
[Inject]
private IAccessTokenProvider AccessTokenProvider { get; set; } = default!;
protected override async Task OnInitializedAsync()
{
hubConnection = new HubConnectionBuilder().WithUrl(
url: new Uri(uriString: "https://localhost:7040/eventhub"),
SetConnectionOptions)
.Build();
hubConnection.On<EventMessage>(
methodName: "ReceiveEventMessageAsync",
ReceiveEventMessageAsync);
await hubConnection.StartAsync();
}
private void SetConnectionOptions(HttpConnectionOptions options) =>
options.AccessTokenProvider = async () => await GetAccessToken();
private async ValueTask<string> GetAccessToken()
{
var accessTokenResult = await AccessTokenProvider.RequestAccessToken();
accessTokenResult.TryGetToken(out var accessToken);
return accessToken.Value;
}
英文:
Have you setup your client to send the token?
[Inject]
private AuthenticationStateProvider AuthenticationStateProvider { get; set; } = default!;
[Inject]
private IAccessTokenProvider AccessTokenProvider { get; set; } = default!;
protected override async Task OnInitializedAsync()
{
hubConnection = new HubConnectionBuilder().WithUrl(
url: new Uri(uriString: "https://localhost:7040/eventhub"),
SetConnectionOptions)
.Build();
hubConnection.On<EventMessage>(
methodName: "ReceiveEventMessageAsync",
ReceiveEventMessageAsync);
await hubConnection.StartAsync();
}
private void SetConnectionOptions(HttpConnectionOptions options) =>
options.AccessTokenProvider = async () => await GetAccessToken();
private async ValueTask<string> GetAccessToken()
{
var accessTokenResult = await AccessTokenProvider.RequestAccessToken();
accessTokenResult.TryGetToken(out var accessToken);
return accessToken.Value;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论