除了标准的现成cookie /表单身份验证之外,我还需要支持SignalR上的HTTPS基本身份验证。 SignalR在混合MVC / WebApi站点的上下文中运行。
在将各个部分放在一起后如何实现这一点,我在服务器上使用了ThinkTecture.IdentityModel.Owin.BasicAuthentication
库,如下所示:
app.Map("/basicauth", map =>
{
map.UseBasicAuthentication("realm", ValidateUser);
map.MapSignalR<AuthenticatedEchoConnection>("/echo");
map.MapSignalR();
});
但是我总是得到一个HTTP 302响应,重定向到MVC站点的Login页面,而不是返回一个挑战。为了更好地调试这个,我快速推出了自己的简单OWIN中间件进行基本身份验证,并得到了相同的结果。使用这样的简单映射进行进一步测试:
app.Map("/test", map =>
{
map.Use((context, next) =>
{
// context.Response.StatusCode = 401;
context.Response.Write("Hello World!");
return Task.FromResult(0);
});
揭示了一个简单的&#34; Hello World&#34;响应正常返回。但是当我注释掉将响应代码设置为401的行时,我再次重定向到“登录”页面。我不明白这种行为......为什么我的MVC网站在这里涉及而不是401响应被返回?我该如何防止这种情况?
对于OWIN,除了上面的特殊/basicauth
映射之外,我在定义的启动方法中只有顶级SignalR映射,它应该继续适用于所有经过cookie验证的调用:
app.MapSignalR();
我没有为OWIN配置任何其他内容。
有人可以帮我吗?
答案 0 :(得分:1)
好的,我找到了解决此问题的方法。第一部分是从第一个样本中删除map.MapSignalR<AuthenticatedEchoConnection>("/echo");
- 这是没有必要的,由于某种原因我没有发现它阻止SignalR正常工作。
第二部分以及实际问题的解决方法是,在客户端中,我还使用第一个请求发送凭据,而不是等待挑战。因此,401永远不会发生,因此没有重定向到登录页面。这对我来说已经足够了。
因此,在客户端中,解决方法是不要像这样使用NetworkCredential:
connection.Credentials = new NetworkCredential(username, password);
相反,请自行添加Authorization标头,以便它已包含在第一个请求中:
string creds = string.format("{0}:{1}", username, password);
string encodedCreds = Convert.ToBase64String(Encoding.Utf8.GetBytes(creds));
connection.Headers.Add("Authorization", "Basic " + encodedCreds);
此外,我发现,对于OWIN,这个问题似乎是一个更普遍的问题,不仅与SignalR甚至Basic Auth一起使用时相关:
因此,通过对基本认证模块的一些修改,还应该可以防止这种重定向。我可能会对此进行调查,并在完成后更新此帖。