Исключить конкретный путь из авторизации WIF в проекте ASP.NET MVC 4

Мы успешно создали фон идентификации Windows (WIF) в нашем проекте ASP.NET 4.5 MVC 4 с помощью расширения Идентификация и доступ... для Visual Studio 2012. Но не могут исключить определенный путь от авторизации, чтобы разрешить анонимный доступ.

Когда мы получаем доступ к нашему маршруту по умолчанию (т.е. /Home), пассивное перенаправление перенаправляет нас на настроенный эмитент Uri. Это верно. Но теперь предположим, что мы хотим исключить Path /Guest из STS Authentication, чтобы каждый мог получить доступ к http://ourhost/Guest, не направляясь к эмитенту STS. Там находятся только статические документы.

Фрагменты из Web.config:

<system.identityModel>
  <identityConfiguration>
    <audienceUris>
      <add value="http://ourhost/" />
    </audienceUris>
    <issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <trustedIssuers>
        <add thumbprint="9B74****40D0" name="OurSTS" />
      </trustedIssuers>
    </issuerNameRegistry>
    <certificateValidation certificateValidationMode="None" />
  </identityConfiguration>
</system.identityModel>
<system.identityModel.services>
  <federationConfiguration>
    <cookieHandler requireSsl="false" />
    <wsFederation passiveRedirectEnabled="true" issuer="http://oursts/Issue" realm="http://ourhost/" reply="http://ourhost/" requireHttps="false" />
  </federationConfiguration>
</system.identityModel.services>

Далее мы имеем...

<system.webServer>
  <!-- ... -->
  <modules runAllManagedModulesForAllRequests="true">
    <add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
    <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
    <remove name="FormsAuthentication" />
  </modules>
</system.webServer>

и, наконец:

<system.web>
  <!-- ... -->
  <authentication mode="None" />
</system.web>

Мы пробовали следующее без успеха:

<location path="~/Guest"> <!-- also "/Guest" is not working -->
  <system.web>
    <authorization>
      <allow users="*" />
    </authorization>
  </system.web>
</location>

Мы также попытались поместить небольшой файл Web.config в эту папку без успеха. Независимо от того, какой Uri мы находим в браузере, мы всегда перенаправляемся.

Каков правильный способ выполнить это?

ИЗМЕНИТЬ

Убрали предыдущий "принятый ответ", установите "принятый ответ" на Eugenios answer, так как это более полезный ответ.

Ответ 1

В приложении MVC вы обычно определяете доступ через атрибут [Authorize] в контроллерах и действиях.

Просто удалите из web.config:

<system.web>
     <authorization>
        <deny users="?" />
      </authorization>

Примечание. Обычно это добавляется автоматически с помощью мастера "Добавить STS Reference" в VS2010

Похоже, что поведение на VS2012 и новых инструментах одинаково. Я просто создал совершенно новое приложение MVC4. Удалил инструмент "Идентификация и доступ..." с локальной конфигурацией STS (оставил все значения по умолчанию).

Он добавил этот фрагмент в web.config:

<authorization>
  <deny users="?" />
</authorization>

Я удалил его и добавил [Authorize] в действие "О программе":

[Authorize]
public ActionResult About()
{
    ViewBag.Message = "Your app description page.";

    return View();
}

Когда я нажимаю ссылку "О", я перенаправляюсь к STS. Все остальное работает с анонимным доступом.

Примечание:

У вас есть контроль над этим тоже в мастере (см. страницу "Конфигурация" мастера).

Ответ 2

Я не могу заставить [Authorize] работать - он не выполняет перенаправление на мой STS, и я уверен, что это то, чего я не вижу. Однако я выяснил, как решить исходный вопрос.

В global.asax:

    protected void Application_Start()
    {
        ... config stuff ...
        FederatedAuthentication.WSFederationAuthenticationModule.AuthorizationFailed += WSFederationAuthenticationModule_AuthorizationFailed;
    }

а затем:

    void WSFederationAuthenticationModule_AuthorizationFailed(object sender, AuthorizationFailedEventArgs e)
    {
        // Do path/file detection here
        if (Request.Path.Contains("/Content/") || Request.Path.Contains("/Scripts/"))
        {
            e.RedirectToIdentityProvider = false;
        }
    }

Ответ 3

Что в конечном итоге указывало мне на правильное направление, было более старое сообщение , в котором объясняется, как защитить определенный контроллер или области страницы. В сочетании с глобальными фильтрами я почти там.

Кажется, что ключ не должен использовать параметр passiveRedirectEnabled="true", но установить его на false. Только тогда у вас есть полный контроль над процессом аутентификации, но вам нужно будет инициировать пассивное перенаправление самостоятельно, используя класс SignInRequestMessage (который это не большое дело).

Приветствуются лучшие решения с меньшим количеством кода.

ИЗМЕНИТЬ

Для этого убрано "принятое состояние ответа", установите "принятый ответ" на Eugenios anwer, так как это более полезный ответ.

Ответ 4

Я был в той же ситуации, что и Томас. В моем случае я тестировал/использовал локальный IISExpress.

Ответ Eugenio почти заставил меня работать, с одним дополнительным требованием. Мне пришлось установить "Анонимная аутентификация" в моем MVC Project Property на "Enabled".

Это было отключено по умолчанию или, возможно, установлено таким образом при использовании инструментария "Идентификация и доступ..." VS 2012.

Итак, чтобы повторить, не было никакого кода или специальных атрибутов для записи/поддержки.

Мой файл csproj содержит:

<IISExpressAnonymousAuthentication>enabled</IISExpressAnonymousAuthentication>

Мой файл web.config содержит:

<system.web>
    <authentication mode="None" />
</system.web>

<system.web>
    <authorization>
        <allow users="*" />
    </authorization>
</system.web>

<system.webServer>
    <modules>
        <remove name="FormsAuthentication" />
        <add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
        <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
    </modules>
</system.webServer>

<system.identityModel.services>
    <federationConfiguration>
        <wsFederation passiveRedirectEnabled="true" issuer="https://REMOVED.accesscontrol.windows.net/v2/wsfederation" realm="urn:REMOVED" requireHttps="false" />
    </federationConfiguration>
</system.identityModel.services>

И я добавляю стандартный атрибут [Authorize] к действиям контроллера, которые я хочу защитить WIF:

[Authorize]
public ActionResult About()
{
....
}