【问题标题】:Authenticate SignalR Hub using ServiceStack Authentication Plugin使用 ServiceStack 身份验证插件对 SignalR Hub 进行身份验证
【发布时间】:2013-01-04 20:13:25
【问题描述】:

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

我还有一个 SignalR Hub,它在同一个 Asp.Net 服务上运行,但 Principal 在我的 Hub 方法上没有经过身份验证。

基本上,我需要 ServiceStack 拦截对我的集线器的调用并验证会话 cookie 并填充 Context.User.Identity 并将其标记为已验证。如果我可以进行设置,我的集线器上的一个简单的 [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 拦截这些请求并设置经过身份验证的用户。

【问题讨论】:

    标签: authentication signalr servicestack


    【解决方案1】:

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

    var cache = AppHostBase.Resolve<ICacheClient>();
    var sess = cache.SessionAs<AuthUserSession>();
    if (!sess.IsAuthenticated)
        throw new AuthenticationException();
    

    【讨论】:

    • 这与我将身份验证 cookie 保存到 SignalR cookie 容器的最初发布的代码结合使用。谢谢!
    【解决方案2】:

    Johan 的回答有效,但是将此代码放在每个方法中并不是很方便,如果将其放在集线器构造函数中,它将在网页刷新时失败,并显示“仅支持通过单例访问的 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;
        }
    
    }
    

    如您所见,代码与 Johan 的答案相同,但它也可以在 Web 中运行,确保在调用 cache.SessionAs 时 HttpContext.Current 不为空

    【讨论】:

      猜你喜欢
      • 2018-07-03
      • 1970-01-01
      • 1970-01-01
      • 2017-03-11
      • 1970-01-01
      • 1970-01-01
      • 2015-09-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多