将IPrincipal从MVC传递到SignalR



我有一个MVC应用程序,带有自定义主体的基于表单的身份验证。在使用应用程序之前,用户必须登录。之后我想使用SignalR,问题是Context.user.Identity.Name总是空字符串。

CustomPrincipal.cs

public class CustomPrincipal : IPrincipal
{
    public CustomPrincipal(IIdentity identity)
    {
        Identity = identity;
    }
    public IIdentity Identity { get; }
    public bool IsInRole(string role)
    {
        return true;
    }
}

CustomIdentity.cs

public class CustomIdentity : IIdentity
{
    public CustomIdentity(EmployeeModel user)
    {
        Name = user.Username;
        Id = user.Id;
    }
    public string AuthenticationType => "Custom";
    public bool IsAuthenticated => !string.IsNullOrEmpty(Name);
    public int Id { get; set; }
    public string Name { get; }
}

BaseController.cs(我从中派生出所有MVC控制器)

protected override void OnAuthorization(AuthorizationContext context)
{
    if (SessionPersister.User != null && !string.IsNullOrEmpty(SessionPersister.User.Username))
    {
        context.HttpContext.User = new CustomPrincipal(new CustomIdentity(SessionPersister.User));
    }
    base.OnAuthorization(context);
}

这里的SessionPersister只是一个静态类,用于存储已登录的用户

所以,我的MVC应用程序中的一切都运行得很好。当用户登录时,我想向另一个通过SignalR登录的用户发送消息,Identity.user.Name是我的Hub类中的空字符串:

public override Task OnConnected()
{
    string name = Context.User.Identity.Name; // it's empty
    return base.OnConnected();
}

有没有任何方法可以将我的MVC IPrincipal传递给SignalR,或者将其配置为使用我在MVC中使用的自定义身份验证?

提前Thanx

因此,轻微的逻辑错误:

BaseController.OnAuthorization仅在执行控制器时触发。当SignalR请求通过时,该方法将永远不会为该请求调用。

因此,解决这一问题的方法是将代码从控制器移动到更全局的范围。例如,您可以使用Global.asax.cs并添加它,如:

    protected void Application_PostAuthenticateRequest( object sender, EventArgs e )
    {
        //do your custom principal setting here.
        this.Context.User = new CustomPrincipal( new CustomIdentity( 10, "test" ) );
    }

然后,在你的集线器中,你可以看到这样的身份:

    public String Hello(String hello)
    {
        //no need to actually cast if you don't need the non-iidentity properties
        //var identity = (CustomIdentity) this.Context.User.Identity;
        //identity.Id == 10
        //identity.Name == "test"
        return hello;
    }

或者,我相信您可以在用户身份验证后将其放入OWIN管道中,而不是Global.asax。然而,其他人需要提供一个确切的例子。

编辑:为了澄清,我更改了CustomIdentity的构造函数,因为我没有您所有的类。上面的例子只是概念的证明。

相关内容

  • 没有找到相关文章

最新更新