我有"正确地";获得了有效的JWT身份验证,尽管我无法让服务器在登录后识别clien的身份(使用JWT或在创建HubConnectionBuilder 时使用cookie
我已经设置SignaLr,在这种情况下通过Id识别用户电子邮件/姓名
连接在使用cookie的情况下,它可以识别客户端。。。直到我创建HubConnection
我为信号员设置用户Id的方式
public class CustomEmailProvider : IUserIdProvider
{
public virtual string GetUserId(HubConnectionContext connection)
{
var res = connection.User?.Claims.FirstOrDefault(x=>x.Type==ClaimTypes.NameIdentifier && x.Value == connection?.User?.Identity?.Name);
return res?.Value;
}
}
使用jwt 的程序中cs
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme/*"Identity.Application"*/;
}).AddJwtBearer(options => {
options.TokenValidationParameters =new TokenValidationParameters()
{
ValidateAudience=true,
ValidateIssuer=true,
ValidateLifetime=true,
ValidateIssuerSigningKey=true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience=builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(builder.Configuration["Jwt:Key"])),
};
});
...
builder.Services.AddHttpClient();
builder.Services.AddSignalR();
builder.Services.AddSingleton<IUserIdProvider, CustomEmailProvider>();
builder.Services.AddResponseCompression(options => options.MimeTypes.Concat(new[] { "application/octet-stream" }));
builder.Services.AddCors(options=>options.AddDefaultPolicy(builder=>builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()));
...
app.UseRouting();
app.UseCors(options => options.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endPoints => { endPoints.MapHub<ConnectionHub>("/ConnectionsHub");
使用cookie
.AddTokenProvider<DataProtectorTokenProvider<AppUser>>(TokenOptions.DefaultProvider);
builder.Services.AddAuthentication("Identity.Application")
.AddCookie();
...
builder.Services.AddSignalR();
builder.Services.AddSingleton<IUserIdProvider, CustomEmailProvider>();
builder.Services.AddResponseCompression(options => options.MimeTypes.Concat(new[] { "application/octet-stream" }));
builder.Services.AddCors(options=>options.AddDefaultPolicy(builder=>builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()))
...
app.UseRouting();
app.UseCors(options => options.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endPoints => { endPoints.MapHub<ConnectionHub>("/ConnectionsHub"); });
app.MapBlazorHub();
在组件中
protected override async Task OnInitializedAsync()
{
if (hub is null)
hub = new HubConnectionBuilder()
.WithUrl(_NavigationManager.ToAbsoluteUri("/ConnectionsHub"))
.Build();
}
因此,在集线器中,当我设置ID中给定的属性[Authorize]时,它没有得到任何标识(在JWT的情况下创建集线器后,它在任何时候都无法识别它(,我想知道如何正确地将标识声明发送到服务器?
创建集线器连接时,需要传递访问令牌。
new HubConnectionBuilder()
.WithUrl(url, options =>
{
options.AccessTokenProvider = () => Task.FromResult("your access token");
});
您还需要使用以下内容配置JwtBearerOptions
:
.AddJwtBearer(options =>
{
// We have to hook the OnMessageReceived event in order to
// allow the JWT authentication handler to read the access
// token from the query string when a WebSocket or
// Server-Sent Events request comes in.
// Sending the access token in the query string is required due to
// a limitation in Browser APIs. We restrict it to only calls to the
// SignalR hub in this code.
// See https://learn.microsoft.com/aspnet/core/signalr/security#access-token-logging
// for more information about security considerations when using
// the query string to transmit the access token.
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("/ConnectionsHub")))
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
SignalR在查询字符串上发送访问令牌,但服务器希望访问令牌在Bearer身份验证标头上。所以我们必须手动阅读。
https://learn.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-6.0#承载令牌认证