SignalR 似乎正在使用 Windows 身份验证而不是使用匿名身份验证

SignalR seems to be using Windows Authentication instead of using Anonymous Authentication

我有一个使用 IIS 10 并启用了 Windows 身份验证和匿名身份验证的 Web 应用程序。该应用程序使用 SignalR 2.4.0 和 SQL 依赖项每十秒循环一次图像,用户可以使用设备停止循环并在返回循环之前按照自己的节奏显示演示文稿。 我遇到的问题是大多数应用程序需要使用 windows 身份验证,并且一些控制器需要允许匿名访问。但是,匿名用户(例如智能电视或未加入域的机器)在未先进行身份验证的情况下无法显示图像。

我可能误解了情况,但我相信这是因为 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,其中包含允许匿名显示控制器和信号器的设置

<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>

我也设置了控制器允许匿名

[AllowAnonymous]
 public class Controller
{
}

PartialView 运行 signalR 脚本在命中时请求身份验证 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
            });

        }
    }
}