我在这里遇到了类似的问题,因为在我的网络应用程序中,我使用了一个简单的 cookie 身份验证系统,它使用 AoP 样式方法来检查任何具有属性的控制器,然后将获取当前上下文(无论是来自静态 HttpContext.Current 还是根据拦截器的类型从目标调用对象),然后验证 cookie 是否存在,它包含正确的数据,然后最后用数据库或缓存等验证令牌。
无论如何,这种方法也可以用于 Signalr,尽管它有点冗长并且您正在使用依赖注入。您基本上将使用所需属性包装集线器调用,然后设置您的 DI/IoC 配置以拦截这些调用,然后在拦截器中获取集线器实例并从请求中获取 cookie(或您的自定义身份验证机制),验证它是否全部有效,如果不是,则抛出一个new HttpException("403", "Not authenticated");
应该将用户踢出并在它甚至击中您的集线器方法之前返回的,这样您就可以将逻辑放在一个地方(您的拦截器或拦截器消耗的类) 然后只需使用您的属性包装需要使用此身份验证的任何方法。
我使用 Ninject 和拦截扩展,但是现在大多数主要的 DI 框架都有某种形式的 IoC 插件/扩展,例如 Autofac、Windsor、Spring 等。
如果您不喜欢将 DI 和/或 AOP 引入当前项目的路线,那么也许您可以创建一个包含身份验证逻辑的自定义集线器实例,然后在集线器中使用它,所以好吧,您仍然会从要保护的每个集线器方法中手动调用一些身份验证逻辑,但代码较少,例如:
public class AuthorisableHub : Hub
{
private ISomeAuthenticationToken GetSomeAuthenticationTokenFromRequest(Request request) // probably a SignalR specific request object
{
// Get your token from the querystring or cookie etc
}
private bool IsAuthenticationTokenValid(ISomeAuthenticationToken token)
{
// Perform some validation, be it simple or db based and return result
}
protected void PerformUserAuthentication()
{
var token = GetSomeAuthenticationTokenFromRequest(Context.Request);
var isRequestValid = IsAuthenticationTokenValid(token);
if(!isRequestValid)
{ throw new HttpException(403, "<Some forbidden message here>"); }
}
}
public class MyFancyPantsHub : AuthorisableHub
{
public void TellAllClientsSomethingSecret(ISecret secret)
{
PerformUserAuthentication();
// Do stuff with the secret as it should have bombed the user out
// before it reaches here if working correctly
}
}
它并不完美,但会起作用(我认为),而且我确信我曾经在某处读到过为每个请求新实例化集线器,如果这确实是真的,如果你想的话,你可以把这个逻辑放在你的构造函数中将身份验证应用于集线器内的每个操作。
希望对您有所帮助,或给您一些想法……有兴趣知道您最终是如何解决它的。