繁体   English   中英

将SignalR Hub与ASP.NET MVC 5项目一起使用时,如何访问用户在Identity 2中的声明?

[英]How can I access the user's Claims in Identity 2 when using SignalR Hub with an ASP.NET MVC 5 project?

我在Asp.Net MVC 5 Framework的顶部有一个使用c#编写的应用程序。

我正在使用SignalR 2.2.2在浏览器和服务器之间创建WebSocket通信,以将消息从服​​务器推送到浏览器。

但是,我需要能够访问已登录用户的ClaimsIdentity对象,以便确定要播客的消息。

通常,我会这样访问身份声明

IPrincipal user = System.Web.HttpContext.Current.User
IIdentity identity = user.Identity;
var claims = (IEnumerable<Claim>)identity.Claims;

但是,此行System.Web.HttpContext.Current返回null; System.Web.HttpContext.Current返回null。 阻止我获取当前登录的用户。

我猜想SignalR创建一个同步连接,这就是System.Web.HttpContext.Current为null的原因。

我也尝试按照此SO Question的建议使用HubCallerContex ,但Context对象也为null。

System.Web.HttpContextBase httpContext = Context.Request.GetHttpContext();

如何在我的中心中正确访问用户声明?

我在使用Framework 4.5.1时将以下密钥添加到Web.config中的appSettings

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>

如果使用SignalR集线器并想在同一集线器下授权方法,则必须使用集线器上的Authorize属性。

[Authorize]
public class MessagingHub: Hub
{
    public Task Send(string data)
    {
        return Clients.Caller.SendAsync("Send", "Data To Send");
    }
}

为了通过集线器方法(例如,上面的“ 发送”)访问声明或用户身份,则必须具有以下内容:

[Authorize]
public class MessagingHub: Hub
{
   public Task Send(string data)
  {
     var identity = (ClaimsIdentity)Context.User.Identity;
     //one can access all member functions or properties of identity e.g, Claims, Name, IsAuthenticated... 
      return Clients.Caller.SendAsync("Send", "Data To Send");
  }
}

如果像我这样使用Json Web令牌(JWT)或仅使用令牌身份验证,那么在客户端,这可以用来调用集线器的Send方法。

注意:就我而言,客户端是Angular 6应用。

import { HubConnection } from "@aspnet/signalr";
import * as signalR from '@aspnet/signalr';
...
private _messagingHubConnection: HubConnection | undefined;
public async: any;
...
constructor(){}
...
 SendMessg(): void {
    if (this._messagingHubConnection) {
      this._messagingHubConnection.invoke('Send');
    }
  }
...

ngOnInit(){
    this._messagingHubConnection= new signalR.HubConnectionBuilder()
      .withUrl("messaging", { accessTokenFactory: () => "jwt_token" }) //have a logic that gets the current user's authentication token from the browser 
      .build();

    this._messagingHubConnection.start().then(() => {
        this.SendMessg();
      }).catch(err => console.error(err.toString()));

    if (this._messagingHubConnection) {
      this._messagingHubConnection.on('Send', (data: any) => {
        //data represents response/message received from Hub method'd return value.
      });

    }
}

注意:我使用的是.Net Core 2.1,因此请务必注册Hub。 这也是假设signalR已经设置

对于.Net Core,请确保在您的StartUp.cs中;

services.AddSignalR(); // under ConfigureServices

app.UseWebSockets();
app.UseAuthentication();
app.UseSignalR(routes => {
    routes.MapHub<LoopyHub>("/messaging");
});

注意:从SignalR在GitHub上问题中,我意识到上述顺序很重要,以防万一有人在开发任何问题。 即根据我的理解,以上顺序是正确的。

从技术上讲,我已经从.NET Core和Angular上下文回答了上面的问题; 我想大多数(如果不是全部)实现都遵循相同的方法。

你们所有人都会错过一件重要的事情。

与控制器不同,您将无法在Hub的构造函数中访问声明。 连接后即可访问声明。 像下面

 [Authorize]
    public class YourHub: Microsoft.AspNetCore.SignalR.Hub
    {

          public override async Task OnConnectedAsync()
          {
             ...
             var identity = (ClaimsIdentity)Context.User.Identity;
          }
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM