ASP.NET MVC пользовательская инъекция IPrincipal

Я работаю над приложением с использованием ASP.NET MVC 1.0, и я пытаюсь внедрить собственный объект IPrincipal в объект HttpContext.Current.User.

В традиционном приложении WebForms я использовал событие Application_AuthenticateRequest, чтобы сделать это следующим образом.

protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {
        if (HttpContext.Current.User != null)
        {
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
                if (HttpContext.Current.User.Identity is FormsIdentity)
                {
                    // Get Forms Identity From Current User
                    FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
                    // Get Forms Ticket From Identity object
                    FormsAuthenticationTicket ticket = id.Ticket;
                    // Create a new Generic Principal Instance and assign to Current User
                    SiteUser siteUser = new SiteUser(Convert.ToInt32(id.Name));

                    HttpContext.Current.User = siteUser;
                }
            }
        }

    }

Таким образом, используя это, я смог получить доступ к своему пользовательскому IPrincipal, либо явно наложив объект User на тип SiteUser. Я на самом деле сделал это, создав собственный класс, который наследует все страницы, из которых это делается под обложками для меня.

Во всяком случае, моя проблема заключается в том, что с ASP.NET MVC приложение Application_AuthenticateRequest срабатывает всякий раз, когда делается какой-либо запрос (например, для файлов JS, изображений и т.д.), из-за чего приложение умирает.

Любая помощь или предложения относительно того, как я могу начать вводить свой пользовательский IPrincipal в объект HttpContext.Current.User в ASP.NET MVC 1.0, будут очень признательны. Я видел следующий пост на SO, но, похоже, он не удовлетворял тем, чего я пытаюсь достичь: ASP.NET MVC - установка пользовательского IIdentity или IPrincipal

ТИА.

Ответ 1

моя проблема в том, что с ASP.NET MVC Application_AuthenticateRequest кажется, срабатывает всякий раз, когда любой запрос (так что для файлов JS, изображений и т.д.) что заставляет приложение умирать.

Это не уникальная проблема MVC - если вы запустили приложение на IIS7 с интегрированным конвейером, то вы увидите то же самое.

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

FormsAuthenticationTicket ticket = id.Ticket;
SiteUser siteUser = new SiteUser(Convert.ToInt32(id.Name));

Я бы предположил, что ваш класс SiteUser выполняет некоторую проверку базы данных. Если вы изучите, как работают формы auth, билет содержит всю информацию, необходимую для создания FormsIdentity (это не относится к ролям, если вы специально не разрешаете кеширование роли в файл cookie). Поэтому вам следует взглянуть на тот же подход. В первый раз, когда вы создаете кеш объекта объекта siteUser в рамках подписанного файла cookie, используйте cookie для регидратации свойств SiteUser при последующих запросах.

Если вы сделаете это, вы можете пойти еще на один шаг, заменив принцип Thread своим SiteUser или, по крайней мере, пользовательской комбинацией IPrincipal/IUser, которая имеет ту же информацию, что и ваш класс SiteUser.

Итак, внутри AuthenticateRequest у вас будет поток вроде

SiteUserSecurityToken sessionToken = null;
if (TryReadSiteUserSecurityToken(ref sessionToken) && sessionToken != null)
{
    // Call functions to attach my principal.
}
else
{
    if (HttpContext.Current.User != null && 
        HttpContext.Current.User.Identity.IsAuthenticated && 
        HttpContext.Current.User.Identity is FormsIdentity)
    {
        // Get my SiteUser object

        // Create SiteUserSecurityToken

        // Call functions to attach my principal.
    }
}

И функция присоединения принципала будет содержать что-то вроде

HttpContext.Current.User = sessionSecurityToken.ClaimsPrincipal;
Thread.CurrentPrincipal = sessionSecurityToken.ClaimsPrincipal;
this.ContextSessionSecurityToken = sessionSecurityToken;

Вы хотите убедиться, что функции, которые записывают токен безопасности в файл cookie, добавляют, как минимум, значение контрольной суммы /MAC и, если хотите, поддерживают шифрование с помощью машинного ключа, если он настроен на выполнение так. Функции чтения должны проверять эти значения.