servicestack,Authentication,Signalr,servicestack" /> servicestack,Authentication,Signalr,servicestack" />

Authentication 使用ServiceStack身份验证插件对信号器集线器进行身份验证

Authentication 使用ServiceStack身份验证插件对信号器集线器进行身份验证,authentication,signalr,servicestack,Authentication,Signalr,servicestack,我在Asp.Net之上创建了一个ServiceStack服务,它实现了基本身份验证。在服务路线上一切正常。我能够登录并获得会话cookie,这些cookie在后续调用中得到验证。我正在使用HttpClient处理这些请求 我还有一个在同一个Asp.Net服务上运行的信号集线器,但是主体没有在我的集线器方法上进行身份验证 基本上,我需要ServiceStack拦截对我的集线器的调用,验证会话cookie,填充Context.User.Identity并将其标记为已验证。如果我可以进行设置,我的hu

我在Asp.Net之上创建了一个ServiceStack服务,它实现了基本身份验证。在服务路线上一切正常。我能够登录并获得会话cookie,这些cookie在后续调用中得到验证。我正在使用HttpClient处理这些请求

我还有一个在同一个Asp.Net服务上运行的信号集线器,但是主体没有在我的集线器方法上进行身份验证

基本上,我需要ServiceStack拦截对我的集线器的调用,验证会话cookie,填充Context.User.Identity并将其标记为已验证。如果我可以进行设置,我的hub上的一个简单的[Authorize]属性将完成其余的工作

以下是我的代码示例:

// set up a HttpClient with a cookie container to hold the session cookie
var cookieJar = new CookieContainer();
var handler = new HttpClientHandler { CookieContainer = cookieJar, UseCookies = true,  UseDefaultCredentials = false };

var client = new HttpClient(handler) { BaseAddress = _baseUri };

client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic",
    Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", userName, password))));

// do client login and get response with session cookie...
var response = client.PostAsync(...);

// add the cookies to the SignalR hub connection
var responseCookies = cookieJar.GetCookies(_baseUri);
var cookieContainer = new CookieContainer();
foreach (Cookie cookie in responseCookies)
{
   cookieContainer.Add(cookie);
}
_hubConnection = new HubConnection(_baseUri.ToString()) { CookieContainer = cookieContainer };

在此设置之后,我的会话cookie将在每次调用时发送到中心。不知何故,我需要ServiceStack拦截这些请求并设置经过身份验证的用户。

让ServiceStack进行身份验证并持久化用户会话。然后在需要身份验证的信号集线器端点中输入以下代码:

var cache = AppHostBase.Resolve<ICacheClient>();
var sess = cache.SessionAs<AuthUserSession>();
if (!sess.IsAuthenticated)
    throw new AuthenticationException();
var cache=AppHostBase.Resolve();
var sess=cache.SessionAs();
如果(!sess.IsAuthenticated)
抛出新的AuthenticationException();

Johan的答案是可行的,但将此代码放到每个方法中并不是很方便,如果将其放入hub构造函数中,它将在网页刷新中失败,出现“仅支持通过单例访问的ASP.NET请求”异常

相反,我选择创建一个自定义属性,该属性为您提供对中心和方法调用授权的更多控制

最简单的属性如下所示:

[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class AuthorizeServiceStack : AuthorizeAttribute
{
    public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request)
    {
        return CheckAuthorization();
    }

    public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
    {
        return CheckAuthorization();
    }

    private static bool CheckAuthorization()
    {
        var cache = AppHostBase.Resolve<ICacheClient>();
        var sess = cache.SessionAs<AuthUserSession>();
        return sess.IsAuthenticated;
    }

}
[AttributeUsage(AttributeTargets.Class,继承=false)]
公共类AuthorizeServiceStack:AuthorizeAttribute
{
公共覆盖bool AuthorizeHubConnection(HubDescriptor HubDescriptor,IRequest请求)
{
返回CheckAuthorization();
}
public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext,bool appliesToMethod)
{
返回CheckAuthorization();
}
私有静态bool CheckAuthorization()
{
var cache=AppHostBase.Resolve();
var sess=cache.SessionAs();
返回sess.IsAuthenticated;
}
}

如您所见,该代码与Johan的答案中的代码相同,但也可以在web上使用,确保在调用cache.SessionAs时,HttpContext.Current不为null,该代码与最初发布的代码(我在其中将auth cookie保存到SignalR cookie容器中)结合使用。谢谢