Подтвердить что ты не робот

Thread.CurrentPrincipal претензий неправильно, чтобы быть anynomous

Я вижу запросы на моем сервере, которые, как представляется, сделаны кем-либо, хотя я уверен, что они были сделаны аутентифицированным пользователем - у меня есть журналы fiddler, показывающие, что клиент отправил действительные cookie файлы asp.net, и журналы сервера, указывающие, что cookie прибыл и действителен. Проблема наблюдается во всех браузерах.

Поток данных:

  • Пользователь посещает URL-адрес входа в систему, на машине, которая является частью webfarm (все с той же машиной, расшифровывают ключи).
  • При успешной аутентификации форм пользователь перенаправляется на ограниченный URL-адрес, на своей домашней странице
  • Домашняя страница отображается правильно, известна идентификация пользователя и включает javascript для выполнения 7 асинхронных пост-обратных связей для получения дополнительных данных.
  • Javascript запускает 7 запросов http.get, ударяя по разным машинам в webfarm (предположим, что вокруг robin)
  • Сервер проверяет запрос: ~ 0.01% не удается выполнить проверку подлинности.

Мысли?

Теперь о деталях:

Очень небольшое число асинхронных запросов приземляется на моем сервере (с доказательствами, что они не были манипулированы или подделаны) и кажутся анонимными. Из 7 выполненных запросов некоторое число может работать или не работать (т.е. 5/7 удастся, 2 не удастся). Кажется, что в успехах/неудачах нет никаких шаблонов. В тех случаях, когда мои запросы кажутся анонимными, CurrentPrincipal.Identity записывает:

Thread.CurrentPrincipal.Identity.IsAuthenticated; // false
Thread.CurrentPrincipal.Identity.Name; // null (or empty, unsure off hand)

Отбрасывая коллекцию http.context.request.params в файл журнала, я могу видеть следующие релевантные (и очищенные) свойства (полные параметры ниже):

context: {"userId":10000,"userName":"johnsmith"}
HTTP_COOKIE:.ASPXAUTH=[valid auth cookie value]
HTTP_X_REQUESTED_WITH:XMLHttpRequest
X-Requested-With: XMLHttpRequest
    AUTH_TYPE: 
    AUTH_USER: 
    AUTH_PASSWORD: 
    LOGON_USER: 
    REMOTE_USER: 
    HTTP_COOKIE: .ASPXAUTH=[valid auth cookie value]

Я знаю, что файл cookie auth действителен - во время этих же запросов я могу расшифровать файл cookie auth и извлечь следующее:

CookiePath: /
Expiration: 9/23/2105 8:14:22 PM
Expired: False
IsPersistent: True
IssueDate: 8/30/2010 2:54:22 PM
Name: johnsmith
UserData: 
Version: 2

Не уверен, как это сделать. Эта проблема, похоже, усугубилась нашей недавней миграцией в mvc 2.0/asp.net 4.0, но моя уверенность не была высокой, что было причиной.

Я обратился к горстке моих клиентов, у которых была эта проблема, и это было еще более неприятно (но отражает то, что я могу читать в своих журналах). Когда-то в этом состоянии ему трудно выбраться. Очистка кеша и файлов cookie, похоже, не имеет никакого эффекта. Но, перейдя на новый браузер, и это вообще нормально. Аналогично, ожидая несколько часов и возвращаясь с тем же браузером, и это также нормально, но не всегда. Как было сказано ранее, это видно во всех браузерах.

Любые предложения?
Кевин




------------
Вот оставшаяся часть фрагмента журнала (очищенная для pii), которую я захватил:

8/30/2010 2:54:43 PM: Anonymous user detected:
    Identity Name:
    IsAuthenticated::False
HttpContextInformation to follow:

8/30/2010 2:54:43 PM: Request Param collection contents:
context: {"userId":10000,"userName":"johnsmith"}
    .ASPXAUTH: A3C6615642F1F543397160C84C0E016C8439BDF400B0130AADAB82C93E77FFF3BEAD7726223F02049FA65B2C3E1773928C0371C4F580F2432C1538551BC5654020AD76F37159BA6BB68D7A68744AE036
    ASP.NET_SessionId: m5vit3cyv0rsiosqg5xmhhuu
    ALL_HTTP: HTTP_CONNECTION:close
HTTP_ACCEPT:text/javascript, text/html, application/xml, text/xml, */*
HTTP_ACCEPT_ENCODING:gzip, deflate
HTTP_ACCEPT_LANGUAGE:en-us
HTTP_COOKIE:.ASPXAUTH=A3C6615642F1F543397160C84C0E016C8439BDF400B0130AADAB82C93E77FFF3BEAD7726223F02049FA65B2C3E1773928C0371C4F580F2432C1538551BC5654020AD76F37159BA6BB68D7A68744AE036
HTTP_HOST:www.host.com
HTTP_REFERER:http://www.host.com/
HTTP_USER_AGENT:Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7
HTTP_X_FORWARDED_FOR:166.137.139.139
HTTP_X_REQUESTED_WITH:XMLHttpRequest

    ALL_RAW: Connection: close
Accept: text/javascript, text/html, application/xml, text/xml, */*
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Cookie: .ASPXAUTH=A3C6615642F1F543397160C84C0E016C8439BDF400B0130AADAB82C93E77FFF3BEAD7726223F02049FA65B2C3E1773928C0371C4F580F2432C1538551BC5654020AD76F37159BA6BB68D7A68744AE036
Host: www.host.com
Referer: http://www.host.com/
User-Agent: Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7
X-Forwarded-For: 166.137.139.139
X-Requested-With: XMLHttpRequest

    APPL_MD_PATH: /LM/W3SVC/792523/Root
    APPL_PHYSICAL_PATH: d:\localpath\
    AUTH_TYPE: 
    AUTH_USER: 
    AUTH_PASSWORD: 
    LOGON_USER: 
    REMOTE_USER: 
    CERT_COOKIE: 
    CERT_FLAGS: 
    CERT_ISSUER: 
    CERT_KEYSIZE: 
    CERT_SECRETKEYSIZE: 
    CERT_SERIALNUMBER: 
    CERT_SERVER_ISSUER: 
    CERT_SERVER_SUBJECT: 
    CERT_SUBJECT: 
    CONTENT_LENGTH: 0
    CONTENT_TYPE: 
    GATEWAY_INTERFACE: CGI/1.1
    HTTPS: off
    HTTPS_KEYSIZE: 
    HTTPS_SECRETKEYSIZE: 
    HTTPS_SERVER_ISSUER: 
    HTTPS_SERVER_SUBJECT: 
    INSTANCE_ID: 792523
    INSTANCE_META_PATH: /LM/W3SVC/792523
    LOCAL_ADDR: 10.248.50.207
    PATH_INFO: /resource
    PATH_TRANSLATED: d:\localpath\resource
    QUERY_STRING: context={%22userId%22:10000,%22userName%22:%22johnsmith%22}
    REMOTE_ADDR: 10.208.205.171
    REMOTE_HOST: 10.208.205.171
    REMOTE_PORT: 37966
    REQUEST_METHOD: GET
    SCRIPT_NAME: /resouce
    SERVER_NAME: www.host.com
    SERVER_PORT: 80
    SERVER_PORT_SECURE: 0
    SERVER_PROTOCOL: HTTP/1.0
    SERVER_SOFTWARE: Microsoft-IIS/6.0
    URL: /resource
    HTTP_CONNECTION: close
    HTTP_ACCEPT: text/javascript, text/html, application/xml, text/xml, */*
    HTTP_ACCEPT_ENCODING: gzip, deflate
    HTTP_ACCEPT_LANGUAGE: en-us
    HTTP_COOKIE: .ASPXAUTH=A3C6615642F1F543397160C84C0E016C8439BDF400B0130AADAB82C93E77FFF3BEAD7726223F02049FA65B2C3E1773928C0371C4F580F2432C1538551BC5654020AD76F37159BA6BB68D7A68744AE036
    HTTP_HOST: www.host.com
    HTTP_REFERER: http://www.host.com/
    HTTP_USER_AGENT: Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7
    HTTP_X_FORWARDED_FOR: 166.137.139.139
    HTTP_X_REQUESTED_WITH: XMLHttpRequest


8/30/2010 2:54:43 PM: Auth Ticket collection contents:
    CookiePath: /
    Expiration: 9/23/2105 8:14:22 PM
    Expired: False
    IsPersistent: True
    IssueDate: 8/30/2010 2:54:22 PM
    Name: johnsmith
    UserData: 
    Version: 2
4b9b3361

Ответ 1

Этот ответ работает, но одновременно вызывает разочарование и тревогу.

Я провел 2 месяца, работая неполный рабочий день с технической поддержкой MSDN, и мы, наконец, нашли работу по этой проблеме. Я собираюсь оставить его в Microsoft, чтобы исправить эту проблему, поскольку это почти наверняка проблема в .NET Framework. Но прежде всего позвольте мне подвести итог этой проблеме, предоставить дополнительную соответствующую справочную информацию и несколько интересных вещей, которые мы нашли на этом пути.

Симптом был мимолетный: на нашем веб-сайте было несколько сообщений о пользователях, которые будут аутентифицироваться на нашем веб-сайте и видеть правильное состояние. Но, по-видимому, случайным образом, они должны быть выписаны из нашего веб-сайта, или изредка, сталкиваются с анонимным представлением. Это было очень неприятно, почти невозможно воспроизвести локально, в доме.

Также по симптомам: через регистрацию мы видели, что на мобильные (iphone, ipad и android) браузеры были непропорционально затронуты, хотя все браузеры и операционные системы в какой-то степени были затронуты. И последний случайный симптом: Itd работает для пользователя один день, а не следующий, а позже днем ​​- снова работать. Конечно, коммутационные браузеры почти всегда устраняли проблему.

Мы быстро взяли вопрос auth, вероятно, вокруг файла cookie аутентификации. Странная часть заключалась в том, что я смог доказать (отслеживание), что запросы, которые были ошибками, включали в себя правильный файл cookie, который я смог расшифровать, но что .net-инфраструктура игнорировалась недетерминированным способом. В конечном итоге я начал регистрировать все запросы, которые были в этом состоянии - auth cookie, проигнорированный инфраструктурой .net, но, по-видимому, действительный для меня, и нашлось около 2% моих пользователей.

Я переключился с использования Thread.CurrentPrincipal.Identity на HttpContext.Current.User.Identity, безрезультатно, и попробовал несколько других настроек. Любопытно, что единственное изменение, которое я смог сделать, сделав вмятину, было перенесено в рамки .net 4 (с 3.5). Проблема стала на порядок хуже. Также попробовал различные конфигурации балансировки нагрузки и смог исключить несколько конфигураций машины - тот же самый компьютер, который выпустил файл cookie, позже отклонил его.

Повторить итерацию симптомов: у нас были определенные пользователи (недетерминированные), которые порой не смогли бы использовать наш веб-сайт в аутентифицированном режиме (также не детерминированном). Милый.

К настоящему времени группа продуктов в Редмонде была вовлечена, а также в тупик. Но они придумали предложение, которое в конечном итоге решило проблему, здесь говорится: Попробуйте заставить среду Microsoft.net использовать куки в качестве режима аутентификации, а не использовать cookieless state:

<authentication mode="Forms">
  <forms cookieless="UseCookies" />
</authentication>

Перевернул переключатель, и мгновенно закончились проблемные запросы (как только я закончил сессию в нечетном состоянии).

Пока я рад, что проблема была решена - или, скорее, работала, - это не детерминированная обработка различных браузеров, которые меня беспокоят. Почему инфраструктура .net видит браузер однажды и обрабатывает его как поддерживающие файлы cookie, а позже в тот же день скажет, что он должен использовать cookieless сессию?

Моя последняя забота о том, сколько других сайтов там теряют 2% их аутентифицированного трафика, не зная? Учитывая исправление, он очень похож на ошибку в инфраструктуре .net 4.

Ответ 2

Не используйте это в аутентификации ASP.NET:

Thread.CurrentPrincipal = principal;

Вместо этого используйте:

HttpContext.Current.User = principal;

Подробнее см. в этой статье текст ссылки, но, что более важно, комментарии, включая первый и последний, - статья старая 2004, но аргументы все еще действуют сегодня.

Следовательно, вместо:

Thread.CurrentPrincipal.Identity.IsAuthenticated; // false Thread.CurrentPrincipal.Identity.Name; // null (or empty, unsure off hand)

Вы должны использовать:

 HttpContext.Current.User.Identity...

В этом случае вы также можете использовать AuthenticateRequest вместо PostAuthenticateRequest, потому что нет проблемы с потоком для обхода.

Ответ 3

Я бы порекомендовал вам начать с проверки того, что входящий веб-запрос фактически имеет cookie проверки подлинности и что он действителен. Модуль проверки подлинности форм принимает входящий веб-запрос и ищет, имеет ли он файл cookie для проверки подлинности. Если это так, то он пытается его декодировать, а затем генерировать принцип, используя его содержащееся значение. Поскольку ваш принцип пуст, это означает, что либо не было cookie аутентификации, содержащегося в запросе, либо было декодирование ошибок, либо оно было декодировано и признано, что оно истекло или оно было декодировано, и, как ни странно, в качестве имени пользователя имеет пустую строку.

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

ForsmAuthentication.Decrypt(...)

Ответ 4

Вот аутентификация, которую я использую для большинства моих приложений ASP.NET/Mvc, для которых требуется базовая аутентификация. Я считаю, что это поможет и позволит вам хранить дополнительные данные в AuthenticationCookie. Если вы используете это раньше .Net делает свою аутентификацию .Net переопределит вашу настройку текущих основных и пользовательских свойств, использование PostAuthenticateRequest исправит главную проблему. Дайте мне знать, если у вас есть вопросы.


// Code that goes in the Global.asax.cs
// that runs after .Net has done it authentication
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
    IPrincipal user = HttpContext.Current.User;

    if (user == null) { return; }

    FormsIdentity formsIdentity = user.Identity as FormsIdentity;

    if (formsIdentity == null || !formsIdentity.IsAuthenticated) { return; }

    Principal principal = new Principal(new Identity(formsIdentity.Ticket));
    HttpContext.Current.User = principal;
    Thread.CurrentPrincipal = principal;
}

// Base implementation of the System.Security.Principal.IPrincipal interface.
public class Principal : System.Security.Principal.IPrincipal
{
    #region Fields

    private IIdentity _identity = null;

    #endregion

    #region Constructors

    public Principal(IIdentity identity)
    {
        _identity = identity;
    }

    #endregion

    #region Properties

    public IIdentity Identity
    {
        get
        {
            return _identity;
        }
    }

    #endregion

    #region Methods

    public bool IsInRole(string role)
    {
        return (_identity != null && _identity.IsAuthenticated);
    }

    #endregion
}



// Base implementation of the System.Security.Principal.IIdentity interface. 
public class Identity : System.Security.Principal.IIdentity
{
    #region Fields

    private readonly int _userId;
    private readonly bool _isAuthenticated;
    private readonly string _userName;

    #endregion

    #region Constructors

    public Identity(FormsAuthenticationTicket formsAuthTicket)
    {
        if (formsAuthTicket == null)
        {
            throw new NullReferenceException("FormsAuthenticationTicket may not be null.");
        }

        if (string.IsNullOrEmpty(formsAuthTicket.UserData))
        {
            throw new NullReferenceException("FormsAuthenticationTicket.UserData may not be null or empty.");
        }

        string[] userData = formsAuthTicket.UserData.Split(new[] {"|"}, StringSplitOptions.RemoveEmptyEntries);

        if (userData.Length < 1)
        {
            throw new ArgumentOutOfRangeException("formsAuthTicket", userData, "UserData does not contain a UserId and or a SiteId");
        }

        _userId = Convert.ToInt32(userData[0]);
        _isAuthenticated = !formsAuthTicket.Expired;
        _userName = formsAuthTicket.Name;
    }

    #endregion

    #region Properties

    public int UserId
    {
        get
        {
            return _userId;
        }
    }
    public string AuthenticationType
    {
        get
        {
            return "Forms";
        }
    }
    public bool IsAuthenticated
    {
        get
        {
            return _isAuthenticated;
        }
    }
    public string Name
    {
        get
        {
            return _userName;
        }
    }

    #endregion
}

Надеюсь, это поможет решить вашу проблему.

Ответ 5

re bounty:

Я вижу это в приложении Azure с asp.net 4.0, здесь есть файл cookie, и вы можете расшифровать его с помощью FormsAuthentication.Decrypt и прочитать все (не истекшее, правильное значение и т.д. и т.д.); как описано в ОП. В отличие от сценария OP, я уже использовал UseCookies и все равно получаю то же самое. Bounty для конкретной причины в asp.net, который может вызвать эту проблему и решение.

Мое дело было такой глупой проблемой:

  • Выдавать токены через FormsAuthentication.SetAuthCookie и соответствующую переадресацию
  • Настройте тег <forms> в файле web.config
  • Проверьте User.Identity.IsAuthenticated на странице /false
  • Файл cookie существует, и вы даже можете его расшифровать с помощью FormsAuthentication.Decrypt

проблема: не забудьте установить <authentication mode="Forms">, lol, total fail...

Мои 2 цента на OP: некоторые внутренние ссылки/переадресации/js могут разрушить хаос при попытке использовать cookieless авторизацию. Кроме того, обнаружение поддержки файлов cookie не очень точно.

Ответ 6

Я полагаю, исходя из моего прошлого опыта, что эта проблема на самом деле вызвана тем, что ASP.NET не распознает IE10+. Не известный браузер и его возможности, он возвращается к аутентификации без cookie (плохое или, по крайней мере, устаревшее предположение).

Обновления для файлов определения браузера были выпущены здесь. Проблема отсутствует с .NET 4.5

https://support.microsoft.com/kb/2600088

http://support.microsoft.com/kb/2600100

http://support.microsoft.com/kb/2608565