Cookie не скользит на сервере, но работает при локальном запуске - PullRequest
0 голосов
/ 21 января 2019

У меня есть приложение Identity server 4 с идентификацией asp .net.У меня есть куки, настроенные на слайд.

services.ConfigureApplicationCookie(opts =>
                        {
                            opts.Cookie.Expiration = TimeSpan.FromDays(30);
                            opts.SessionStore = new RedisCacheTicketStore(new RedisCacheOptions()
                            {
                                Configuration = configuration["Redis:HostPort"]
                            }, logger, configuration);
                            opts.Cookie.SameSite = SameSiteMode.None;
                            opts.SlidingExpiration = true;
                            opts.ExpireTimeSpan = TimeSpan.FromDays(30);
                        }
                    );

Не скользит

Локальный хост: Когда пользователь входит в систему .AspNetCore.Idenitty.Application, он получает время истечения.Когда страница обновляется, срок действия обновляется, я вижу изменение метки времени.

Производство: Однако, если я проверяю это, когда он активен на сервере, пользователь входит в систему, и. AspNetCore.Idenitty.Application получает время истечения сотметка времени, когда вы вошли в систему. Однако при обновлении страницы отметка времени не изменяется.Он остается таким же, каким был при входе пользователя в систему.

enter image description here

Пользователь выгнал через 30 минут

Производство: Вторая проблема заключается в том, что, как вы видите, срок действия установлен на месяц вперед, но когда на сервере через 30 минут этого пользователя выгонят и заставят снова войти в систему.Я не могу держать пользователя в системе более 30 минут, даже если он активен.

Метка безопасности

Я проверил, что маркер безопасности пользователей не изменился, и токен содержит "AspNet.Identity.SecurityStamp": "[users actual key]"

Обновление

Так что после некоторого раскопок я, наконец, решил перебрать проверку штампов безопасностиЯ сделал это, перебрав следующие методы в моем ApplicationSignInManager

 public override async Task<ApplicationUser> ValidateSecurityStampAsync(ClaimsPrincipal principal)
        {
            if (principal == null)
            {
                Logger.LogError(LoggingEvents.ApplicationSignInManagerSecurityTokenValidation, "ClaimsPrincipal is null");
                return null;
            }
            var user = await UserManager.GetUserAsync(principal);
            if (await ValidateSecurityStampAsync(user, principal.FindFirstValue(Options.ClaimsIdentity.SecurityStampClaimType)))
            {
                return user;
            }

            if(user == null)
                Logger.LogError(LoggingEvents.ApplicationSignInManagerSecurityTokenValidation, "User not found [principal {principal}]", principal);

            var principalSecurityStamp = principal.FindFirstValue(Options.ClaimsIdentity.SecurityStampClaimType);  // Security stamp from claims
            var userManagerSecurityStamp = user.SecurityStamp;                                                     // Security Stamp from usermanager
            var getSecurityStampAsyncResults = await UserManager.GetSecurityStampAsync(user);                      // Security stamp from GetSecurityStampAsync
            Logger.LogError(LoggingEvents.ApplicationSignInManagerSecurityTokenValidation,
                "Security stamp Validation Failed: [principalSecurityStamp {principalSecurityStamp}] != [getSecurityStampAsyncResults {getSecurityStampAsyncResults}] also ([userManagerSecurityStamp {userManagerSecurityStamp}] )", principalSecurityStamp, getSecurityStampAsyncResults, userManagerSecurityStamp);

            return null;
        }

        public virtual async Task<bool> ValidateSecurityStampAsync(ApplicationUser user, string securityStamp)
            => user != null &&
               // Only validate the security stamp if the store supports it
               (!UserManager.SupportsUserSecurityStamp || securityStamp == await UserManager.GetSecurityStampAsync(user));

Это привело к тому, что в моем журнале мгновенно появилась очень интересная информация.

Сбой проверки безопасности: [PrincipalSecurityStamp (null)]! = [getSecurityStampAsyncResults 83270b3f-a042-4a8f-b090-f5e1a084074e] также ([userManagerSecurityStamp 83270b3f-a042-4a8f-b090 * * * * * 10 * 10 * 1044) 1074 044 1040 044 040 1074 074 1074 074 074 074 074 074 074 074 074 074 074 074 074 074 424ноль.Почему я не знаюЯ также не знаю, как это исправить, так как есть ряд сторонних приложений, вызывающих этот сервер идентификации.

update2:

Теперь я могу проверить, что GenerateClaimsAsync действительно устанавливает SecurityStampClaim.Однако CookieValidatePrincipalContext в ValidateAsync не содержит рассматриваемое утверждение, что странно, как говорится в комментарии к методу.

/// <param name="context">The context containing the <see cref="System.Security.Claims.ClaimsPrincipal"/>

Ответы [ 2 ]

0 голосов
/ 31 января 2019

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

Сначала проблема была с маркером безопасности.Токен безопасности сохраняется в пользовательской таблице. Когда создается файл cookie identity.application, этот токен сохраняется в куки.Каждые пять минут приложение связывается с сервером идентификации и проверяет, требуется ли проверка токена.Если он старше тридцати минут, маркер безопасности будет проверен.(Обратите внимание, что время пяти минут и тридцати минут настраивается, это просто значения по умолчанию)

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

Выпуск номер один

SignInManager.cs # L260 проверяет токен безопасности, но не проверяет, является ли он нулевым.

Таким образом, если с файлом cookie что-то не так, и токен по какой-либо причине является нулевым либо в базе данных, либо в моем случае он был перезаписан другим файлом cookie, то пользователь будет входить в систему в течение тридцати минут, а затем вылетит первымвремя пытается проверить токен безопасности.что привело к выдаче запроса # 7055 .Файл cookie следует проверять каждый раз, чтобы убедиться, что в нем есть токен безопасности.

Номер выпуска 2

Следующая строка кода обозначает пользователя и создаетcookie, хранящий защищенный токен в указанном cookie

var signInUserResult = await _signInManager.PasswordSignInAsync(userName, password, rememberMe, true);

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

await HttpContext.SignInAsync(user.Id.ToString(), user.UserName, props);
0 голосов
/ 22 января 2019

" SlidingExpiration имеет значение true, чтобы дать указание обработчику повторно выдавать новый файл cookie с новым временем истечения каждый раз, когда он обрабатывает запрос, который находится более чем на полпути через окно истечения срока действия." В течение 30-дневного периода истечения срока действия новый файл cookie не будет выдаваться в течение первых 15 дней. Первый запрос через 15 дней выдаст обновленный файл cookie.

Время ожидания 30 минут, вероятно, исходит от средства проверки штампов безопасности , которое запускается только каждые 30 минут (проверка обходится дорого). Похоже, ваши штампы неправильно сгенерированы или проверены. Вы вообще настроили или настроили этот компонент?

Примечание: удалить opts.Cookie.Expiration , игнорируется.

...