将 IPrincipal 从 MVC 传递到 SignalR
Pass IPrincipal from MVC to 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只是一个静态的class用来存储登录用户
因此,我的 MVC 应用程序中的所有内容都运行良好。当用户登录并且我想向通过 SignalR 登录的另一个用户发送消息时,Identity.User.Name 在我的 Hub class:
中是一个空字符串的问题
public override Task OnConnected()
{
string name = Context.User.Identity.Name; // it's empty
return base.OnConnected();
}
有什么方法可以将我的 MVC IPrincipal 传递给 SignalR 或将其配置为使用我在 MVC 中使用的自定义身份验证?
提前致谢
所以,轻微的逻辑错误:
BaseController.OnAuthorization
仅在执行控制器时触发。当 SignalR 请求通过时,该方法将 永远不会 为该请求调用。
因此,一种解决方法是将代码从 Controller 移动到更全局的范围。例如,您可以使用 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 的构造函数,因为我没有您的全部 类。上面的例子只是概念证明。
我有一个 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只是一个静态的class用来存储登录用户
因此,我的 MVC 应用程序中的所有内容都运行良好。当用户登录并且我想向通过 SignalR 登录的另一个用户发送消息时,Identity.User.Name 在我的 Hub class:
中是一个空字符串的问题public override Task OnConnected()
{
string name = Context.User.Identity.Name; // it's empty
return base.OnConnected();
}
有什么方法可以将我的 MVC IPrincipal 传递给 SignalR 或将其配置为使用我在 MVC 中使用的自定义身份验证?
提前致谢
所以,轻微的逻辑错误:
BaseController.OnAuthorization
仅在执行控制器时触发。当 SignalR 请求通过时,该方法将 永远不会 为该请求调用。
因此,一种解决方法是将代码从 Controller 移动到更全局的范围。例如,您可以使用 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 的构造函数,因为我没有您的全部 类。上面的例子只是概念证明。