У меня есть приложение Identity Server 4, которое я пытаюсь запомнить (сохранить) логин пользователя.
Я думаю, что отследил проблему до чего-то в Redis.
Когда билеты хранятся в Redis, они хранятся с тайм-аутом.
127.0.0.1:6379> ttl Ids-v2-Local-Key-74c112d5-e0f4-48c4-9d0f-cd8e62f12dfd
(integer) 3014
Пока приложение открыто, Redis будет обновлять тайм-аут.
1542808250.760394 [0 lua] "EXPIRE" "Ids-v2-Local-Key-74c112d5-e0f4-48c4-9d0f-cd8e62f12dfd" "3600"
Это нормально, пока пользователь активен в приложении, ключ которого продолжает обновляться.Однако, если пользователь возвращается домой и возвращается на следующий день, его приложение больше не входит в систему.
Я смог исправить это, вручную войдя в Redis и установив ключ для Persist
127.0.0.1:6379> Persist XenaIdentityserver-v2-Local-Key-74c112d5-e0f4-48c4-9d0f-cd8e62f12dfd
(integer) 1
127.0.0.1:6379> ttl XenaIdentityserver-v2-Local-Key-74c112d5-e0f4-48c4-9d0f-cd8e62f12dfd
(integer) -1
Я думаю, проблема в том, как создаются ключи в Redis.
RedisCacheTicketStore
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Redis;
using Microsoft.Extensions.Logging;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
namespace Xena.IdentityServer.Services
{
public class RedisCacheTicketStore : ITicketStore
{
private readonly ILogger _logger;
private string KeyPrefix = "AuthSessionStore-";
private IDistributedCache _cache;
public RedisCacheTicketStore(RedisCacheOptions options, ILogger logger, IConfiguration config)
{
KeyPrefix = config["Redis:ApplicationName"] + "-";
_logger = logger;
_cache = new RedisCache(options);
}
public async Task<string> StoreAsync(AuthenticationTicket ticket)
{
var sw = new Stopwatch();
sw.Start();
var guid = Guid.NewGuid();
var key = KeyPrefix + guid.ToString();
await RenewAsync(key, ticket);
_logger.LogDebug(LoggingEvents.RedisCacheTicketStore, "Redis Method StoreAsync Elapsed {sw.ElapsedMilliseconds}", sw.ElapsedMilliseconds);
return key;
}
public Task RenewAsync(string key, AuthenticationTicket ticket)
{
var sw = new Stopwatch();
sw.Start();
var options = new DistributedCacheEntryOptions();
var expiresUtc = ticket.Properties.ExpiresUtc;
if (expiresUtc.HasValue)
{
options.SetAbsoluteExpiration(expiresUtc.Value);
}
options.SetSlidingExpiration(TimeSpan.FromMinutes(60));
byte[] val = SerializeToBytes(ticket, _logger);
_cache.Set(key, val, options);
sw.Stop();
_logger.LogDebug(LoggingEvents.RedisCacheTicketStore, "Redis Method RenewAsync Elapsed {sw.ElapsedMilliseconds}", sw.ElapsedMilliseconds);
return Task.FromResult(0);
}
public Task<AuthenticationTicket> RetrieveAsync(string key)
{
var sw = new Stopwatch();
sw.Start();
AuthenticationTicket ticket;
byte[] bytes = null;
bytes = _cache.Get(key);
ticket = DeserializeFromBytes(bytes, _logger);
sw.Stop();
_logger.LogDebug(LoggingEvents.RedisCacheTicketStore, "Redis Method RetrieveAsync Elapsed {sw.ElapsedMilliseconds}", sw.ElapsedMilliseconds);
return Task.FromResult(ticket);
}
public Task RemoveAsync(string key)
{
var sw = new Stopwatch();
sw.Start();
_cache.Remove(key);
sw.Stop();
_logger.LogDebug(LoggingEvents.RedisCacheTicketStore, "Redis Method RemoveAsync Elapsed {sw.ElapsedMilliseconds}", sw.ElapsedMilliseconds);
return Task.FromResult(0);
}
private static byte[] SerializeToBytes(AuthenticationTicket source, ILogger logger)
{
var sw = new Stopwatch();
sw.Start();
var ticket = TicketSerializer.Default.Serialize(source);
sw.Stop();
logger.LogDebug(LoggingEvents.RedisCacheTicketStore, "Redis Method SerializeToBytes Elapsed {sw.ElapsedMilliseconds}", sw.ElapsedMilliseconds);
return ticket;
}
private static AuthenticationTicket DeserializeFromBytes(byte[] source, ILogger logger)
{
var sw = new Stopwatch();
sw.Start();
var hold = source == null ? null : TicketSerializer.Default.Deserialize(source);
sw.Stop();
logger.LogDebug(LoggingEvents.RedisCacheTicketStore, "Redis Method DeserializeFromBytes Elapsed {sw.ElapsedMilliseconds}", sw.ElapsedMilliseconds);
return hold;
}
}
}
Я могу перейти по коду и увидеть, что AuthenticationTicketустановите isPersistant при переходе через метод StoreAsync.Однако он не создает постоянный тикет, на котором все еще есть время ожидания.
Как мне сообщить _cache.Set (key, val, options);установить постоянный билет, а не один с тайм-аутом?