Как выполнять интеграционные тесты веб-API ASP.NET с настраиваемой проверкой подлинности и размещением в памяти

На аналогичный вопрос был дан ответ здесь, но ответ, похоже, не работает в моем случае.

Я хочу протестировать процесс аутентификации/авторизации в моем веб-API, который использует аутентификацию JWT.

Моя аутентификация обрабатывается с помощью пользовательского MessageHandler, который я добавляю в свой HttpConfiguration. Авторизация обрабатывается простым атрибутом [Authorize] в контроллере/методах, к которым я хочу ограничить доступ.

Я устанавливаю принцип, который я извлек из своего токена, таким образом во время аутентификации (в моем пользовательском MessageHandler):

Thread.CurrentPrincipal = principal;

if (HttpContext.Current != null)
{
     HttpContext.Current.User = principal;
}

Весь этот процесс работает нормально, когда я тестирую его вручную в локальном IIS.

Но при тестировании с хостингом в памяти, например здесь, свойство ApiController.User, хранящее принципала, которое используется для авторизации с помощью [Authorize], получает Thread.CurrentPrincipal в моем вызывающем тесте (основной Windows моего текущего сеанса) вместо того, который был установлен во время аутентификации. Если я установлю для своего Thread.CurrentPrincipal значение null, я получу только плохие запросы.

TL;DR Как протестировать конвейер аутентификации/авторизации с размещением в памяти? Поскольку он устанавливает значение ApiController.User в значение Thread.CurrentPrincipal в моем тесте и не получает значение, которое я успешно установил во время аутентификации.

Я думаю, что мне удастся обойти это, внедрив пользовательский атрибут [Authorize], получающий Thread.CurrentPrincipal, а не ApiController.User, но я бы хотел этого избежать.

Заранее спасибо.

EDIT для уточнения: весь этот конвейер (аутентификация, а затем авторизация) работает нормально, размещенный в работающем IIS (с HttpContext, который является нулевым во время размещения в памяти). Я просто пытаюсь протестировать его с хостингом в памяти (если это возможно). Во время тестирования с хостингом в памяти, поставив точки останова в моем пользовательском MessageHandler, я могу сказать, что Thread.CurrentPrincipal настроен правильно, просто [Authorize], похоже, не заботится об этом, так как в моих ApiControllers свойство ApiController.User уже установлено на значение моего значения Thread.CurrentPrincipal в моем тесте (мой локальный участник сеанса Windows)


person Dace    schedule 28.03.2014    source источник
comment
какую версию веб-API ASP.NET вы используете здесь? Вы можете опубликовать код обработчика сообщений, который аутентифицирует запросы?   -  person tugberk    schedule 28.03.2014
comment
Я использую ASP.NET Web API 2.1 и здесь вы можете найти несколько похожий обработчик сообщений для аутентификации запросов (линия 110, я не использую PrincipalTransformer, но сразу назначаю принципала, который я получаю от tokenHandler.ValidateToken)   -  person Dace    schedule 28.03.2014


Ответы (1)


Мне удалось выполнить рекомендации, перечисленные в "Получение и назначение текущего принципала". " главы 15 в разделе "Разработка Evolvable Web APIs with ASP.NET":

В веб-API ASP.NET версии 2.0 эту проблему можно решить с помощью нового класса HttpRequestContext. Во-первых, текущее удостоверение должно быть извлечено и присвоено текущему объекту запроса, а не статическому свойству. Во-вторых, разные хосты могут использовать разные реализации HttpRequestContext.

Короче говоря, в обработчике сообщений сделайте это вместо установки текущего принципала Thread и HttpContext:

request.GetRequestContext().Principal = principal;
person Rafael Dowling Goodman    schedule 12.07.2014
comment
После 2 дней поиска решения это сработало для меня. Спасибо. - person Jose; 01.07.2019