Обновление приложения ASP.NET 3.5 до ASP.NET 4.5 и сопутствующие проблемы: общая система аутентификации с использованием форм.

Мне часто приходится заниматься проблемами миграции старых приложений ASP.NET на более новые версии. И независимо от того насколько много документации по этому поводу предоставляет Microsoft и насколько богатый опыт накопился у сообщества за последнее время, невозможно избежать новых проблем на которые тратится много человеко-часов. Даже несмотря на то, что статьи в MSDN описывают проблемы миграции в розовом цвете, реальность всё же сильно другая. Именно решению подобных проблем будет посвящён данный цикл статей, точнее весь мой опыт который накопился за всё это время. В данной статье будет рассмотрен случай переноса веб-приложения ASP.NET 3.5 на платформу ASP.NET 4.5.1 и проблема разделения куки-файла аутентификации (стандартно это .ASPXAUTH cookie) между разными приложениями. Как известно, ASP.NET поддерживает проверку подлинности с помощью форм в распределенной среде: либо между приложениями на одном сервере, либо на веб-ферме. И данная возможность часто используется в крупных веб-приложениях. Проблема в общих чертах вглядит так, у нас есть несколько веб-приложений ASP.NET 3.5 работающих в веб-ферме, назовём их A, B, С, D, E . Для всех из них используется единый механизм аутентификации и авторизации на основе форм. Приложение A основное, у остальных отсуствует собственная логика системы авторизации и аутентификации, они разделяют её с A. Нам нужно перенести A, B, С, D с ASP.NET 3.5 на ASP.NET 4.5.1, E оставляем. Начинать можно с данного руководства, на пути будет много препятствий (сильно специфичных для проекта, но данная статья только об одном), которые нужно будет преодолеть с помощью могучего интернета (полезными также будут вот эта документ и это руководство). Допустим всё проходит гладко, ну или почти всё. Открываем наш сайт A, логинимся, переходим на сайт B, нас туда не пускают. Самое главное, всё отлино работает на старой платформе. Пытаемя выяснить причины. Первым делом проверяем идентичность настроек секций <authentication> и <machineKey> .

 <authentication mode="Forms">
  <forms path="/" loginUrl="~/Default.aspx" protection="All"
 domain=".mydomain.com" timeout="2000"
 name=".ASPXAUTH"
 slidingExpiration="true">
  </forms>
</authentication>
<machineKey 
 validationKey="A2734932DA6EE8B5917A35C2BA8536DE3E14074C415EE45417CD7"
 decryptionKey="4171F954D13C3C2DDF7C3551283C4"
 validation="SHA1"
></machineKey>
 

Обратите внимание, что в примере, для экономии места, приведены фиктивные значения validationKey и decryptionKey, реальные же намного длинее. Убедившись что всё идентично, запускаем приложения, не работает аутентификации. Разница платформ, однозначно да. Смотрим логи сервера, находим: Event code: 4005 Event message: Forms authentication failed for the request. Reason: The ticket supplied was invalid. Нужно проверить настройки IIS, не была ли включена генерация случайных ключей на уровне IIS, также нужно проверить аккаунты от имени которых работают пулы, на идентичность. Была и такая проблема с приложениями C и D, решение описано здесь. Те кто регулярно наблюдал и наблюдает за изменениями в платформе .NET наверняка помнят, что в .NET 4.5 были внесены криптографические улучшения остальным пришлось бы потрать больше времени в поисках. Прочитав все три части становится понятно, откуда может быть проблема, дело в арибуте targetFramework узла <httpRuntime targetFramework="4.5.1" /> . Он попросту отсутствует в старых версиях web.config, хотя присутствует по умолчанию в новых. Как и почему, всё описано здесь. А что касается приложения E, его по тем или иным причинам невозможно перенести на новую платформу. В этом случае возникает другая проблема, проблема разных механизмов шифрования, котрая решается добавлением атрибута compatibilityMode в тег <machineKey compatibilityMode="Framework20SP1" /> . Также была проблема и с requestValidationMode, решается удалением этого атрибута из <httpRuntime requestValidationMode="2.0" /> . Значения атрибутов и элементов конфигураций не были описаны детально, более подробное описание можно найти в MSDN или по приведённым ссылкам. В итоге получаем, что общие решения не всегда работают, каждое приложени в своём роде уникально. Надеюсь, что данная статья окажется полезной, если вы сталкнётесь с подобным.