gregor.tusar
09/25/2024, 11:41 PMpublic class DistributedCacheComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
if (ServerInfo.Role == ServerRole.SchedulingPublisher)
{
builder.AddNotificationHandler<UmbracoApplicationStartingNotification, RunAddCacheTableMigration>();
}
builder.Services.AddDistributedSqlServerCache(options =>
{
options.SchemaName = "dbo";
options.TableName = nameof(CacheStore);
options.ConnectionString = builder.Config.GetConnectionString("umbracoDbDSN");
});
}
}
Startup:
public void ConfigureServices(IServiceCollection services)
{
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
options.Cookie.Name = "custom_session_cookie";
});
....
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSession();
.....
}
Is ther something special we need to do on user login action, or do we need a special middleware?
Help would really be apriciated ❤️DortL7L7L7
09/25/2024, 11:53 PMgregor.tusar
09/25/2024, 11:58 PMvar result = await signInManager.PasswordSignInAsync(
user?.UserName ?? model.Username, model.Password, model.RememberMe, true);
if (result.Succeeded)
{
HttpContext.Session.SetString("UserId", user.Id.ToString());
return Ok(ModelState);
}
But the table in the SQL remained empty, even though I got the cookie I set for session in the browser.DortL7L7L7
09/26/2024, 12:18 AMgregor.tusar
09/26/2024, 3:18 PMSession
and configured SessionStore
Startup.cs
cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSession();
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.SameSite = SameSiteMode.Lax;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
// Use the distributed cache for storing security stamps
options.SessionStore = new DistributedCacheTicketStore(
services.BuildServiceProvider().GetRequiredService<IDistributedCache>());
});
}
gregor.tusar
09/26/2024, 3:19 PMITicketStore
interface:
DistributedCacheTicketStore.cs
cs
namespace Cms.SessionStore
{
// Example taken from: https://github.com/bitwarden/server/blob/2e072aebe3a1354965b0018de620703133fec501/src/Core/IdentityServer/DistributedCacheTicketStore.cs
public class DistributedCacheTicketStore(IDistributedCache cache) : ITicketStore
{
private const string KeyPrefix = "auth-";
public async Task<string> StoreAsync(AuthenticationTicket ticket)
{
var key = $"{KeyPrefix}{Guid.NewGuid()}";
await RenewAsync(key, ticket);
return key;
}
public Task RenewAsync(string key, AuthenticationTicket ticket)
{
var options = new DistributedCacheEntryOptions();
var expiresUtc = ticket.Properties.ExpiresUtc ?? DateTimeOffset.UtcNow.AddMinutes(30);
options.SetAbsoluteExpiration(expiresUtc);
options.SetSlidingExpiration(TimeSpan.FromMinutes(30));
var val = SerializeToBytes(ticket);
cache.Set(key, val, options);
return Task.FromResult(0);
}
public Task<AuthenticationTicket?> RetrieveAsync(string key)
{
AuthenticationTicket? ticket;
var bytes = cache.Get(key);
ticket = DeserializeFromBytes(bytes ?? []) ?? default;
return Task.FromResult(ticket);
}
public Task RemoveAsync(string key)
{
cache.Remove(key);
return Task.FromResult(0);
}
private static byte[] SerializeToBytes(AuthenticationTicket source)
{
return TicketSerializer.Default.Serialize(source);
}
private static AuthenticationTicket? DeserializeFromBytes(byte[] source)
{
return (source is null) ? default : TicketSerializer.Default.Deserialize(source);
}
}
}
gregor.tusar
09/26/2024, 3:19 PMDistributedCacheComposer
cs
public class DistributedCacheComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
if (ServerInfo.Role == ServerRole.SchedulingPublisher)
{
builder.AddNotificationHandler<UmbracoApplicationStartingNotification, RunAddCacheTableMigration>();
}
builder.Services.AddDistributedSqlServerCache(options =>
{
options.SchemaName = "dbo";
options.TableName = nameof(CacheStore);
options.ConnectionString = builder.Config.GetConnectionString("umbracoDbDSN");
});
}
}
gregor.tusar
09/26/2024, 3:19 PMDataProtection
package which helped with sharing data protection keys between the pods
Cms.proj
<PackageReference Include="Umbraco.Community.DataProtection" Version="13.0.0" />
Without that package, we only got sessions in the cache from each pod and they were not reused.
Hope it helps someone.kdx-perbol
09/26/2024, 5:42 PMTempData
for some reason, which is only technically related to session state.
I'm surprised you had to implement your own ticket store, what was the reason for that?gregor.tusar
09/27/2024, 7:42 AM