我一直在构建一个Web服务,到目前为止,它完全由ASP.NET Web API调用组成。我现在需要将SignalR添加到混音中,但我想知道如何保持安全方面的一致性。
我目前正在使用OAuth承载令牌(使用OWIN身份验证),因此我的客户端基本上会有一个access_token,我通常会将其添加到任何Web API调用的标头中。但是,我如何使用SignalR做同样的(或类似的)?我可以在创建连接时或每次通话时进行身份验证吗?而且,最重要的是,我如何首先指定访问令牌?
感谢。
答案 0 :(得分:1)
我已经编写了一个样本,帮助了一些已经使用SignalR身份验证的人。 我希望它也可以帮助你。
https://github.com/louislewis2/AngularJSAuthentication
Barguast,对不起我的回答简短。通过链接你可能会理解,有太多的动作部分让我准确地写出你应该注意的最重要部分的解释。示例代码包含三个项目,您将只关注.Api和.Web项目。
如果有任何部分需要进一步澄清或指导,请告诉我,我很乐意帮助您,因为所有其他人都需要相同的例子,这就是我被要求建立的原因这个例子首先出来了。
答案 1 :(得分:1)
(太晚了:D,但可能对某人有用) 您可以在客户端的hubConnection中添加accessTokenFactory,然后在后端(asp.net core 3.1)中对其进行检查。
在BackEnd中,您必须覆盖JwtBearerEvents并检查OnMessageReceived内部的access_token以及集线器端点路径
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
// other options here ... //
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/ConnectionHub"))) // for me my hub endpoint is ConnectionHub
{
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
从客户端添加您的accessToken选项(TypeScript):
public async startConnection(): Promise<void> {
this.hubConnection = new signalR.HubConnectionBuilder()
.withUrl('https://localhost:5001/ConnectionHub', { // ConnectionHub is hub endpoint
accessTokenFactory: () => this.getAccessToken(),
skipNegotiation: true,
transport: signalR.HttpTransportType.WebSockets
}).build();
await this.hubConnection.start();
// ....
}
getAccessToken(): string {
return UserData.token !== undefined ? UserData.token : ''; // Where UserData.token is a jwt token
}
微软说: 各个中心方法也可以应用[Authorize]属性
[Authorize]
public class ChatHub : Hub
{
public async Task Send(string message)
{
// ... send a message to all users ...
}
[Authorize("Administrators")]
public void BanUser(string userName)
{
// ... ban a user from the chat room (something only Administrators can do) ...
}
}
最后,您可以在中心的任何方法内阅读和检查声明或身份属性:
public override async Task OnConnectedAsync()
{
// Get UserID. Assumed the user is logged before connecting to chat and userid is saved in session.
string userID = Context.User.Identity.Name;
// Get ChatHistory and call the client function. See below
await GetHistoryAsync(userID);
await base.OnConnectedAsync();
}