我已经花了一个多月的时间来解决这个问题,但无济于事。
目标是在 Blazor 服务器应用的 Signalr 中心获取用户声明。我在我的 Github 上上传了一个非常简单的应用程序。客户端可以通过单击按钮调用集线器上的方法,集线器方法会发回带有 User.Identity.Name 的消息。但是,由于用户声明为空,我无法获取名称。
这里是存储库: https://github.com/aadurham/blazorserverauth
很多人在这里和其他地方问同样的问题。信息/建议/解决方案是分散的。事实证明,我(可能对我的编程水平的任何人来说)都无法将这些部分组合在一起并使它们工作。
我怀疑一个优秀的程序员不会花太多时间将这些部分放在上面的简单应用程序中。我相信很多人,包括我自己,都会从中受益。我希望一些好心的撒玛利亚人可以伸出援手。在这种情况下,请提出拉取请求。我会保留代码供其他人使用,稍后会尝试添加手册。我还会回来尝试使用同样简单的 Blazor WASM 应用程序做同样的事情。
非常感谢
答案 0 :(得分:1)
来自这个仓库 https://github.com/BrianLParker/SignalRAuth
protected override async Task OnInitializedAsync()
{
hubConnection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri("/chathub"), options =>
{
options.AccessTokenProvider = async () =>
{
var accessTokenResult = await AccessTokenProvider.RequestAccessToken();
accessTokenResult.TryGetToken(out var accessToken);
return accessToken.Value;
};
})
.Build();
hubConnection.On<string, string>("ReceiveMessage", (user, message) =>
{
var encodedMsg = $"{user}: {message}";
messages.Add(encodedMsg);
StateHasChanged();
});
await hubConnection.StartAsync();
}
[Authorize]
public class ChatHub : Hub
{
private readonly UserManager<ApplicationUser> userManager;
public ChatHub(UserManager<ApplicationUser> userManager)
{
this.userManager = userManager;
}
public async Task SendMessage(string user, string message)
{
var userId = Context.UserIdentifier;
var applicationUser = await userManager.FindByIdAsync(userId);
await Clients.All.SendAsync("ReceiveMessage", applicationUser.Email, message);
}
}
答案 1 :(得分:1)
我想出了一个简单的解决方案,虽然不完美但很好。我的目标是将一些用户信息传递给集线器,以便我可以使用 userid(或任何喜欢的用户信息)注册 connectionid。迄今为止我未能实施的可用解决方案建议在连接上添加令牌。相反,我将用户信息添加到标题并在集线器上提取它,如下所示:
这是客户端代码:
@code{
[CascadingParameter]
private Task<AuthenticationState> _authstate { get; set; }
private HubConnection connection;
private AuthenticationState authstate { get; set; }
private List<string> messages = new List<string>();
protected override async Task OnInitializedAsync()
{
authstate = await _authstate;
if (authstate != null)
{
var userid = authstate.User.Identity.Name;
connection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri("/myhub"), options => {
options.Headers.Add("USERID", userid);
})
.WithAutomaticReconnect()
.Build();
connection.On<string, string>("ReceiveMessage", ReceiveMessage);
await connection.StartAsync();
}
}
public void ReceiveMessage(string user, string msg)
{
messages.Add(user + " " + msg);
StateHasChanged();
}
public async void InvokeSomething()
{
await connection.InvokeAsync("InvokeSomething");
}
}
这是我在集线器上提取用户信息的方式:
public async Task InvokeSomething()
{
var httpCtx = Context.GetHttpContext();
var name = httpCtx.Request.Headers["USERID"].ToString();
await Clients.All.SendAsync("ReceiveMessage", name, " invoked this");
}`
它有效。在 OnConnectedAsync 中也使用相同的方法。
希望这对某人有所帮助。 github repo 中的更新代码。
集线器上的 Authorize 属性使应用程序崩溃。所以我认为与集线器的连接没有经过身份验证(微软文档声称我们不需要做任何其他事情)。我希望有比我更好的技能的人提供更好的解决方案。与此同时,这似乎起到了作用。
找到解决方案 为了启用 Hub 类的授权,必须将用户通过身份验证时创建的安全 cookie 传递给 Blazor 服务器 SPA 应用程序。您应该在创建集线器连接时传递 cookie。这将允许您通过 Context 对象访问 Hub 中的所有声明,例如 UserIdentofier 和 UserName。