203 lines
6.9 KiB
C#
203 lines
6.9 KiB
C#
using System;
|
|
using System.Threading.Tasks;
|
|
using gehGassi.Core.Interfaces;
|
|
using gehGassi.Web.Helper;
|
|
using Microsoft.AspNetCore.Authentication;
|
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
|
using Microsoft.Extensions.Caching.Memory;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace gehGassi.Web.Auth
|
|
{
|
|
/// <summary>
|
|
/// Ticketstore für AuthenticationTickets
|
|
/// </summary>
|
|
public class MemoryCacheTicketStore : ITicketStore
|
|
{
|
|
private readonly IOptions<SessionSettings> _sessionSettings;
|
|
private const string KeyPrefix = "AuthSessionStore-";
|
|
private IMemoryCache _cache;
|
|
|
|
public MemoryCacheTicketStore(IOptions<SessionSettings> sessionSettings)
|
|
{
|
|
_sessionSettings = sessionSettings;
|
|
_cache = new MemoryCache(new MemoryCacheOptions());
|
|
}
|
|
|
|
public async Task ClearAll()
|
|
{
|
|
await Task.Delay(1);
|
|
_cache.Dispose();
|
|
_cache = new MemoryCache(new MemoryCacheOptions());
|
|
}
|
|
|
|
public async Task<string> StoreAsync(AuthenticationTicket ticket)
|
|
{
|
|
var key = KeyPrefix + ticket.Principal.Identity.Name;
|
|
await RenewAsync(key, ticket);
|
|
return key;
|
|
}
|
|
|
|
public Task RenewAsync(string key, AuthenticationTicket ticket)
|
|
{
|
|
if (!key.StartsWith(KeyPrefix))
|
|
key = KeyPrefix + key;
|
|
|
|
var options = new MemoryCacheEntryOptions();
|
|
var expiresUtc = ticket.Properties.ExpiresUtc;
|
|
if (expiresUtc.HasValue)
|
|
{
|
|
options.SetAbsoluteExpiration(expiresUtc.Value);
|
|
}
|
|
options.SetSlidingExpiration(TimeSpan.FromMinutes(_sessionSettings.Value.TimeOut));
|
|
|
|
_cache.Set(key, ticket, options);
|
|
|
|
return Task.FromResult(0);
|
|
}
|
|
|
|
public Task<AuthenticationTicket> RetrieveAsync(string key)
|
|
{
|
|
if (!key.StartsWith(KeyPrefix))
|
|
key = KeyPrefix + key;
|
|
|
|
AuthenticationTicket ticket;
|
|
_cache.TryGetValue(key, out ticket);
|
|
return Task.FromResult(ticket);
|
|
}
|
|
|
|
public Task RemoveAsync(string key)
|
|
{
|
|
if (!key.StartsWith(KeyPrefix))
|
|
key = KeyPrefix + key;
|
|
|
|
_cache.Remove(key);
|
|
return Task.FromResult(0);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ticketstore für AuthenticationTickets der diese initial von einer DB lädt und wieder speichern kann.
|
|
/// Übersteht "Server-Resets"
|
|
/// </summary>
|
|
public class MemoryCachePersistedTicketStore : ITicketStore
|
|
{
|
|
private bool _initialized;
|
|
private IServiceProvider _serivceProvider;
|
|
private readonly IOptions<SessionSettings> _sessionSettings;
|
|
private const string KeyPrefix = "AuthSessionStore-";
|
|
private IMemoryCache _cache;
|
|
|
|
public MemoryCachePersistedTicketStore(IOptions<SessionSettings> sessionSettings, IServiceProvider serviceProvider)
|
|
{
|
|
_serivceProvider = serviceProvider;
|
|
_sessionSettings = sessionSettings;
|
|
_cache = new MemoryCache(new MemoryCacheOptions());
|
|
_initialized = false;
|
|
}
|
|
|
|
private async Task InitializeAsync()
|
|
{
|
|
using var scope = _serivceProvider.CreateScope();
|
|
var persistedTicketService = scope.ServiceProvider.GetRequiredService<IPersistedTicketService>();
|
|
var items = await persistedTicketService.GetAllAsync();
|
|
foreach (var item in items)
|
|
{
|
|
var options = new MemoryCacheEntryOptions();
|
|
var expiresUtc = item.Expires;
|
|
if (expiresUtc.HasValue)
|
|
{
|
|
options.SetAbsoluteExpiration(expiresUtc.Value);
|
|
}
|
|
options.SetSlidingExpiration(TimeSpan.FromMinutes(_sessionSettings.Value.TimeOut));
|
|
|
|
if (!_cache.TryGetValue(item.Key, out var value))
|
|
_cache.Set(item.Key, DeserializeFromBytes(item.Ticket), options);
|
|
}
|
|
_initialized = true;
|
|
}
|
|
|
|
public async Task ClearAll()
|
|
{
|
|
await Task.Delay(1);
|
|
_cache.Dispose();
|
|
_cache = new MemoryCache(new MemoryCacheOptions());
|
|
}
|
|
|
|
public async Task<string> StoreAsync(AuthenticationTicket ticket)
|
|
{
|
|
if (!_initialized)
|
|
await InitializeAsync();
|
|
|
|
var key = KeyPrefix + ticket.Principal.Identity.Name;
|
|
await RenewAsync(key, ticket);
|
|
return key;
|
|
}
|
|
|
|
public async Task RenewAsync(string key, AuthenticationTicket ticket)
|
|
{
|
|
if (!_initialized)
|
|
await InitializeAsync();
|
|
|
|
if (!key.StartsWith(KeyPrefix))
|
|
key = KeyPrefix + key;
|
|
|
|
var options = new MemoryCacheEntryOptions();
|
|
var expiresUtc = ticket.Properties.ExpiresUtc;
|
|
if (expiresUtc.HasValue)
|
|
{
|
|
options.SetAbsoluteExpiration(expiresUtc.Value);
|
|
}
|
|
options.SetSlidingExpiration(TimeSpan.FromMinutes(_sessionSettings.Value.TimeOut));
|
|
|
|
_cache.Set(key, ticket, options);
|
|
|
|
using var scope = _serivceProvider.CreateScope();
|
|
var persistedTicketService = scope.ServiceProvider.GetRequiredService<IPersistedTicketService>();
|
|
|
|
var userId = key.Replace(KeyPrefix, "");
|
|
var expires = ticket.Properties.ExpiresUtc;
|
|
var byteTicket = SerializeToBytes(ticket);
|
|
|
|
await persistedTicketService.SaveAsync(key, userId, byteTicket, expires);
|
|
await persistedTicketService.CommitAsync("System");
|
|
}
|
|
|
|
public async Task<AuthenticationTicket> RetrieveAsync(string key)
|
|
{
|
|
if (!_initialized)
|
|
await InitializeAsync();
|
|
|
|
if (!key.StartsWith(KeyPrefix))
|
|
key = KeyPrefix + key;
|
|
|
|
AuthenticationTicket ticket;
|
|
_cache.TryGetValue(key, out ticket);
|
|
return ticket;
|
|
}
|
|
|
|
public async Task RemoveAsync(string key)
|
|
{
|
|
if (!_initialized)
|
|
await InitializeAsync();
|
|
|
|
if (!key.StartsWith(KeyPrefix))
|
|
key = KeyPrefix + key;
|
|
|
|
_cache.Remove(key);
|
|
|
|
using var scope = _serivceProvider.CreateScope();
|
|
var persistedTicketService = scope.ServiceProvider.GetRequiredService<IPersistedTicketService>();
|
|
await persistedTicketService.RemoveAsync(key);
|
|
await persistedTicketService.CommitAsync("System");
|
|
}
|
|
|
|
private byte[] SerializeToBytes(AuthenticationTicket source)
|
|
=> TicketSerializer.Default.Serialize(source);
|
|
|
|
private AuthenticationTicket DeserializeFromBytes(byte[] source)
|
|
=> source == null ? null : TicketSerializer.Default.Deserialize(source);
|
|
}
|
|
}
|