Переписывание URL-адресов .net для локализации, проблемы с аутентификацией форм и loginUrl

StackOverflow https://stackoverflow.com/questions/1213550

Вопрос

Я использую HttpModule для перезаписи URL-адресов на многоязычном сайте.В HttpModule я добавляю обработчик события BeginRequest и ищу первую часть пути, содержащую имя культуры.

Например, /fr-ca/index.aspx будет перезаписан в /index.aspx, а культура потока и культура пользовательского интерфейса будут установлены на 3084.Это работает нормально.

Введите аутентификацию с помощью форм.Аутентификация с помощью форм по-прежнему работает нормально с несопоставленным URL-адресом, но если пользователь не авторизован, он будет перенаправляться на loginUrl, как установлено в разделе аутентификации файла web.config, и включать параметр ?ReturnUrl= querystring для обработки перенаправления обратно на запрошенный странице после аутентификации пользователя.

Здесь возникают две проблемы, если пользователь запрашивает страницу на языке, отличном от языка по умолчанию:

  1. LoginUrl игнорирует путь до его перезаписи.
  2. Параметр ReturnUrl также игнорировал необработанный путь.

Это эквивалентно Request.Url.PathAndQuery вместо Request.RawUrl.

Вместо этого я не могу перейти в конвейер при событии AuthorizeRequest, потому что тогда мне придется защищаться от всех возможных значений региональных параметров, поскольку я использую один файл web.config с несколькими путями к местоположению.Это также не решает первую проблему.

Я просмотрел FormsAuthenticationModule в рефлекторе и вижу, где можно изменить его, чтобы решить №1 и №2, но он, конечно, запечатан.

Я также много просмотрел, но не вижу никаких работоспособных решений.

FormsAuthenticationModule проверяет заголовок 401, созданный в UrlAuthorizationModule.Если вы ищете реферер (который пуст) на странице loginUrl, это подтвердится.

Есть предположения?

РЕДАКТИРОВАТЬ № 1

Я использую IIS 6, и IIS 7 не вариант.

РЕДАКТИРОВАТЬ № 2

Страница входа не подбирала культуру/культуру пользовательского интерфейса по умолчанию, потому что когда я создавал локальный ресурс (представление дизайна:Инструменты > Создать локальный ресурс), IDE добавила в директиву страницы следующее:

культура="авто" мета:resourcekey="PageResource1" uicultural="авто"

Будьте осторожны с этим в vs.net 2008!По крайней мере, это решает одну из проблем, связанных с отсутствием ссылки на культуру по умолчанию, но №1 и №2 все еще не решены.

РЕДАКТИРОВАТЬ 3

Я надеялся, что смогу перейти к одному из событий конвейера и выполнить собственное перенаправление, но в разделе «Отражение метода OnEnter System.Web.Security.UrlAuthorizationModule» я узнал, что после установки заголовка 401 метод вызывает application.CompleteRequest, который как вы можете догадаться, это приводит нас прямо к событию EndRequest.Это то, что модуль FA выполняет перенаправление, и я боюсь, что не смогу сразу выполнить собственное перенаправление!Я удивлен, что больше людей не сталкивается с этой проблемой, или, возможно, они еще не присоединились.


Пример:

У меня есть раздел участника в физической папке /members/, защищенный проверкой подлинности с помощью форм.

В web.config у меня есть:

<authentication mode="Forms">
  <forms loginUrl="~/members/login.aspx" timeout="40" />
</authentication>

и...

  <location path="members">
      <system.web>
          <authorization>
              <deny users="?" />
              <allow roles="Members" />
              <deny users="*" />
          </authorization>
      </system.web>
  </location>

Когда неаутентифицированный пользователь запрашивает индексную страницу /members/, он перенаправляется на loginUrl из раздела аутентификации выше с помощью FormsAuthenticationModule.Он также добавляет параметр ?ReturnUrl к запрошенной странице.

Это прекрасно работает, если пользователь просматривает веб-сайт, используя культуру по умолчанию, но мой HttpModule устанавливает культуру на основе присутствия имени культуры в первой части пути.

Итак, /fr-ca/members/index.aspx перезаписывается в /members/index.aspx и устанавливает культуру/культуру пользовательского интерфейса на канадский французский язык.К сожалению, FormsAuthenticationModule отправляет пользователя на страницу loginUrl с переписанным URL-адресом, а не с исходным.Таким образом, настройки культуры потеряны, а URL-адрес перенаправления неверен.

Надеюсь, это поможет @Greg

Это было полезно?

Решение

Хорошо, проблема решена.

Оказывается, ключом была очистка httpModules Machine.config, добавление моего собственного httpModule, а затем обратное добавление необходимых httpModules по умолчанию.Это позволило моему пользовательскому httpModule перейти к событию EndRequest перед FormsAuthenticationHttpModule.

<httpModules>
    <clear/>
    <!-- custom -->
    <add name="LocalizationHttpModule" type="LocalizationHttpModule"/>
    <!-- add back defaults, exlude PassportAuthentication, AnonymousIdentification, Profile -->
    <add name="OutputCache" type="System.Web.Caching.OutputCacheModule" />
    <add name="Session" type="System.Web.SessionState.SessionStateModule" />
    <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" />
    <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
    <add name="RoleManager" type="System.Web.Security.RoleManagerModule" />
    <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
    <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" />

</httpModules> 

Затем в моем пользовательском httpModule я просто подключаюсь к EndRequest, ищу код состояния 401 и перенаправляюсь по своему желанию.По сути, я переписываю код метода FormsAuthenticationHttpModule OnLeave в соответствии со своими потребностями.

Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init

    Dim authentication As AuthenticationSection = WebConfigurationManager.GetSection("system.web/authentication")
    If authentication.Mode = AuthenticationMode.Forms Then
        Me._LoginUrl = authentication.Forms.LoginUrl
        AddHandler context.EndRequest, AddressOf Context_EndRequest
    End If

End Sub

Private Sub Context_EndRequest(ByVal sender As Object, ByVal e As EventArgs)
    Dim application As HttpApplication = DirectCast(sender, HttpApplication)
    Dim context As HttpContext = application.Context

    If (context.Response.StatusCode = &H191) Then                
       ' do custom redirect here
    End If

End Sub

Другие советы

Единственное, о чем я могу думать, это выполнить перенаправление на форму входа вручную.

1) Разрешить всем доступ к каталогу участников
2) Все страницы членства напрямую наследуются от подкласса Page.
3) В PreInit(?) подкласса Page проверьте, является ли пользователь членом роли членства.
4) Если нет, создайте URL-адрес страницы входа самостоятельно, включая параметр ReturnURL, и перенаправьте пользователя на ваш URL-адрес входа.

Вы также можете взломать это, поместив несколько разделов <location> в свой web.config.бывший:< location path="fr-ca/members">< аутентификация>< form loginUrl="~/fr-ca/members/login.aspx">... но я действительно понятия не имею.

Вероятно, есть другие способы сделать это, с которыми я не знаком.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top