使用带有signalR的blazor服务器作为中继服务器



目标是使用signalR将Blazor服务器用作中继服务器。在此之前,我几乎没有使用blazor服务器的经验。我们的想法是将Winform/Xamarin客户端连接到该服务器,使用现有数据库中的名称/id定位收件人,并中继必要的信息。

中心:

[Authorize]
public class ChatHub : Hub
{
public Task SendMessageAsync(string user, string message)
{
//Context.UserIdentifier
Debug.WriteLine(Context.UserIdentifier);
Debug.WriteLine(Context?.User?.Claims.FirstOrDefault());
return Clients.All.SendAsync("ReceiveMessage", user, message); ;
}
public Task DirectMessage(string user, string message)
{
return Clients.User(user).SendAsync("ReceiveMessage", user, message);
}
}

根据文档,我试图设置上下文。UserIdentifier,但是我在身份验证部分遇到了困难。我的program.cs是这样的:

var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
services.AddTransient<IUserIdProvider, MyUserIdProvider>();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{

//var accessToken = context.Request.Query["access_token"];
var accessToken = context.Request.Headers["Authorization"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/chathub"))
{
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSignalR();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
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.UseStaticFiles();
app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.MapBlazorHub();
app.MapHub<ChatHub>("/chathub");
app.MapFallbackToPage("/_Host");
app.Run();

对于我的客户端(一个winform测试客户端),我尝试了这样做:

HubConnection chatHubConnection;
chatHubConnection = new HubConnectionBuilder()
.WithUrl("https://localhost:7109/chathub", options =>
{
options.AccessTokenProvider = () => Task.FromResult(token);
})
.WithAutomaticReconnect()
.Build();

private async void HubConBtn_Click(object sender, EventArgs e)
{
chatHubConnection.On<string, string>("ReceiveMessage", (user, message) =>
{
this.Invoke(() =>
{
var newMessage = $"{user}: {message}";
MessagesLB.Items.Add(newMessage);
});
});
try
{
await chatHubConnection.StartAsync();
MessagesLB.Items.Add("Connected!");
HubConBtn.Enabled = false;
SendMessageBtn.Enabled = true;
}
catch (Exception ex)
{
MessagesLB.Items.Add(ex.Message);
}
}

作为第一步,我只是想验证一个用户/检查它是否在实时数据库中,如果是这样,连接并填写:上下文。UserIdentifier,这样我就可以在Hub中使用它。我知道我可能需要一个中间件,但我真的不知道究竟如何测试connectionId/Jwt令牌或类似的获取用户/连接。

如果有任何正确的提示,我将不胜感激。

如果我理解你的问题,你不知道在哪里以及如何生成JWT令牌。

对我来说,JWT令牌应该从服务器(您的集线器)生成。

POST api/auth,在playload你给登录+ SHA256密码和返回JWT令牌。

一旦你检查了用户授权在你的数据库中是正确的,你可以发出令牌。

为了生成JWT令牌,我使用这段代码:
public string GenerateToken(IConfiguration Config, DateTime? expire)
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, userName),
new Claim(JwtRegisteredClaimNames.Jti, _id),
new Claim(ClaimsIdentity.DefaultRoleClaimType, role)
};
// ClaimsIdentity.DefaultRoleClaimType
var bytes = Encoding.UTF8.GetBytes(Config["jwt:Secret"]);
var key = new SymmetricSecurityKey(bytes);
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
//Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
var token = new JwtSecurityToken(
//Config.GetValue<string>("jwt:Issuer"),
//Config.GetValue<string>("jwt:Issuer") + "/ressources",
claims: claims,
expires: DateTime.Now.AddMinutes(Config.GetValue<int>("jwt:ExpireMinute")),
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
}

#编辑

看这里允许JWT用于SignalR

https://learn.microsoft.com/en us/aspnet/core/signalr/authn -和- authz?view=aspnetcore - 6.0

我还添加了这个

services.AddAuthorization(auth =>
{
auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
.RequireAuthenticatedUser().Build());
});

最简单的解决方案是使用IdentityServer之类的东西来处理身份验证。这是一个免费的解决方案,也是基于。net的,它只需要很少的配置工作就可以为您提供简单的客户端凭据认证并为您生成令牌。

我基本上就是你在这里问的:一个WinForms应用程序连接到我的signalR hub应用程序在远程服务器上,使用承载令牌-但我也有OIDC/OAUTH实现与第三方用户帐户登录。

IdentityServer提供了一个很好的完整示例库,向您展示了所有流程—只需更改几行代码,您就拥有了一个完整的身份验证系统,可以轻松增强。

使用IdentityServer,您可以获得所有内容,甚至是使signalR hub应用程序能够从令牌中包含的声明创建声明主体(也称为用户)的相应扩展方法。

在这里你可以找到所有的例子和文档:https://github.com/IdentityServer/IdentityServer4

如果你遇到了什么问题,就在这里回复,我会尽力帮助你。

相关内容

  • 没有找到相关文章

最新更新