我有一个使用 IIS 10 并启用了 Windows 身份验证和匿名身份验证的 Web 应用程序。该应用程序使用 SignalR 2.4.0 和 SQL 依赖项每十秒循环一次图像,用户可以使用设备停止循环并在返回循环之前按照自己的节奏显示演示文稿。 我遇到的问题是大多数应用程序需要使用 Windows 身份验证,并且一些 Controller 需要允许匿名访问。但是,匿名用户(例如智能电视或未加入域的机器)在未先进行身份验证的情况下无法显示图像。
我可能误解了情况,但我相信这是因为 signalR 使用的是 Windows 身份验证。如果我关闭要求输入用户名和密码的对话框,Microsoft Edge 的控制台将显示以下消息
HTTP401: DENIED - 请求的资源需要用户身份验证。 (XHR)GET - http://MyWebsite/Home/signalr/negotiate?clientProtocol=2.0&connectionData=%5B%7B%22name%22%3A%22signalrhub%22%7D%5D&_=1557410422010
我尝试过的大部分代码更改都在 web.config 中。主 web.config 文件有认证模式
<authentication mode="Windows" />
不过,我还有一个版本 web.config,其中包含允许显示 Controller 和信号器匿名的设置
<location path="Area/Controller" xdt:Transform="InsertIfMissing" xdt:Locator="Match(path)">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
<location path="signalr" xdt:Transform="InsertIfMissing" xdt:Locator="Match(path)">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
我的第一个想法是我需要为位置路径添加一个通配符,这样它看起来像
<location path="signalr/*" xdt:Transform="InsertIfMissing" xdt:Locator="Match(path)">
或
<location path="signalr/negotiate*" xdt:Transform="InsertIfMissing" xdt:Locator="Match(path)">
但是通过四处搜索和测试似乎不接受它。
我也尝试过明确允许对路径进行匿名身份验证,但在到达身份验证阶段之前我收到错误 500
<location path="Area/Controller" xdt:Transform="InsertIfMissing" xdt:Locator="Match(path)">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="true" />
</authentication>
</security>
</system.webServer>
</location>
<location path="signalr" xdt:Transform="InsertIfMissing" xdt:Locator="Match(path)">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="true" />
</authentication>
</security>
</system.webServer>
</location>
我还设置了 Controller 允许匿名
[AllowAnonymous]
public class Controller
{
}
运行 signalR 脚本的 PartialView 在点击 connection.hub.start 时要求进行身份验证
<input type="hidden" name="connectionId" id="connectionId" />
<div id="divImageViewer"></div>
@Scripts.Render("~/bundles/jquery_signalR")
<script src="@Model.SignalRHubsUrl" type="text/javascript"></script>
@Html.HiddenFor(model => Model.MyModel.ModelItem)
<script type="text/javascript">
$(function () {
setTimeout(function () {
$.connection.hub.start()
.done(function () {
console.log("starting..."); //doesn't display in the console
var cid = $.connection.hub.id;
$("#connectionId").val(cid);
console.log("connected! Id: " + cid);
//do stuff
})
.fail(function (reason) {
console.log("SignalR connection failed: " + reason); //does display in the console after closing the dialog box
});
}, 5000); // Start connection after 5 seconds.
}
</script>
最终,我希望为大多数 Web 应用程序保留 Windows 身份验证,但仍允许对一些小部分进行匿名访问。
如果其中大部分都是无用的胡言乱语,我也很抱歉,其中很多对我来说仍然是新的,尤其是 javascript 和 jquery。
最佳答案
在获得一些帮助后设法将范围缩小到下面注释掉的行。一旦删除,SignalR 就可以毫无问题地匿名通过。
[assembly: OwinStartupAttribute(typeof(Go.Startup))]
namespace MyName
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var container = CompositionRoot.Compose();
var controllerFactory = new InjectableControllerFactory(container);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
MvcSiteMapProviderConfig.Register(container);
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
//GlobalHost.HubPipeline.RequireAuthentication(); <---------
app.MapSignalR(new HubConfiguration
{
EnableJSONP = true,
EnableJavaScriptProxies = true,
EnableDetailedErrors = true
});
}
}
}
关于c# - SignalR 似乎正在使用 Windows 身份验证而不是使用匿名身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56062694/