好的,所以我一直在玩SignalR一段时间。我有一个包含以下项目的VS2013解决方案:
这些在本地运行时,使用hosts文件转发域。它们在不同的域上运行,因为我希望SignalR与任何其他项目完全分开运行(因为它也可以通过某些桌面软件,也可能是iOS应用程序访问)。
在Mvc网站上,正在运行一个小留言板。包括留言板在内的整个网站都是表格身份验证的背后。我通过SignalR检索电路板的所有消息,使用Javascript调用自定义GetMessages
上的MessageHub
函数:
$(function () {
// Declare a proxy to reference the hub.
var signalrUrl = SignalrBaseUrl + '/signalr';
var messageList = $('#messageList');
var messenger = $.connection.messengerHub;
messenger.client.addMessage = function (message) {
addMessageToList(message);
};
function init() {
messenger.server.getAllMessages().done(function (messages) {
messageList.empty();
addMessagesToList(messages);
})
}
[...]
// Start the connection.
$.connection.hub.url = signalrUrl;
$.connection.hub.logging = SignalrLogging;
$.connection.hub.start().done(init);
})
我希望只有经过身份验证的用户才能访问集线器以及所有集线器。我知道设置Authorize属性(或通过配置强制对所有集线器进行身份验证),我的问题是关于身份验证部分。
那么如何正确完成身份验证?我相信只要我们在不同的域上(有人可以确认吗?),共享cookie就不会起作用。为此,我需要以某种方式使用Mvc网站中创建的Cookie(我猜?)来使用,但我不知道如何将它发送到SignalR以及将它与之比较?或者将用户名和密码发送到SignalR并在那里对businesslayer中的Membership provider进行身份验证?实现这一目标的最佳模式是什么?任何想法都将不胜感激。
答案 0 :(得分:6)
最后,通过查看表单身份验证的单点登录技术的一些示例,我找到了解决方案。基本上我做的是:
将以下内容添加到MVC和SignalR web.config:
<authentication mode="Forms">
<forms name="MyCookieName" domain=".domain.nl" cookieless="AutoDetect" loginUrl="My/Login/Url" timeout="525600" />
</authentication>
<machineKey validationKey="12345etc" decryptionKey="cte54321" validation="SHA1" decryption="AES" />
两个项目在主域名domain.nl下运行非常重要(例如subdomain1.domain.com和subdomain2.domain.com)。机器密钥用于cookie和票证加密,应在web.configs中设置。 (更多信息:http://www.codeproject.com/Articles/27576/Single-Sign-on-in-ASP-NET-and-Other-Platforms)
在mvc项目中,cookie像往常一样在登录后设置:
FormsAuthentication.SetAuthCookie(loginName, true);
我使用chrome开发人员工具检查cookie是否设置正确。出于测试目的,我将以下内容放在我的信号器中心,在if语句中放置一个断点:
if (Context.User.Identity.IsAuthenticated)
{
}
然后用户不为空,并且IsAuthenticated为真。
最后我添加了
GlobalHost.HubPipeline.RequireAuthentication();
在我的SignalR Startup类中,确保只有经过身份验证的用户才能访问任何集线器。在登录之前,我现在在尝试访问集线器时收到401未授权。登录后,cookie由mvc网站创建,该网站与SignalR共享,可以到达集线器。像魅力一样工作,比我想象的要简单得多!