gpt4 book ai didi

Azure/网络场就绪的 SecurityTokenCache

转载 作者:行者123 更新时间:2023-12-03 12:51:40 24 4
gpt4 key购买 nike

我们的网站使用 ADFS 进行身份验证。为了减少每个请求的 cookie 负载,我们打开 IsSessionMode(请参阅 Your fedauth cookies on a diet)。

要使其在负载平衡环境中正常工作,我们需要做的最后一件事是实现一个农场就绪的 SecurityTokenCache。实现看起来非常简单,我主要感兴趣的是找出在处理 SecurityTokenCacheKey 以及 TryGetAllEntries 和 TryRemoveAllEntries 方法时是否应该考虑任何问题(SecurityTokenCacheKey 有 Equals 和 GetHashCode 方法的自定义实现)。

有人有这方面的例子吗?我们计划使用 AppFabric 作为后备存储,但使用任何持久存储的示例都会有所帮助 - 数据库表、Azure 表存储等。

以下是我搜索过的一些地方:

  • Hervey Wilson's PDC09session他用一个数据库安全 token 缓存。我还没找到样本他的 session 的代码。
  • Vittorio Bertocci 优秀著作第 192 页在《Programming Windows Identity Foundation》一书中,他提到了上传Azure 就绪的 SecurityTokenCache 的示例实现书的网站。我也没有找到这个样本。

谢谢!

京东

2012 年 3 月 16 日更新 Vittorio's blog使用新的 .net 4.5 内容的示例链接:

ClaimsAwareWebFarm这个示例是对我们从你们许多人那里得到的反馈的回答:您想要一个显示场就绪 session 缓存(而不是 tokenreplycache)的示例,以便您可以通过引用使用 session 而不是交换大 cookie;您需要一种更简单的方法来保护农场中的 cookie。

最佳答案

为了提出一个有效的实现,我们最终必须使用反射器来分析 Microsoft.IdentityModel 中与 SessionSecurityToken 相关的不同类。以下是我们的想法。此实现部署在我们的开发和质量保证环境中,似乎工作正常,它对应用程序池回收等具有弹性。

在 global.asax 中:

protected void Application_Start(object sender, EventArgs e)
{
FederatedAuthentication.ServiceConfigurationCreated += this.OnServiceConfigurationCreated;
}

private void OnServiceConfigurationCreated(object sender, ServiceConfigurationCreatedEventArgs e)
{
var sessionTransforms = new List<CookieTransform>(new CookieTransform[]
{
new DeflateCookieTransform(),
new RsaEncryptionCookieTransform(
e.ServiceConfiguration.ServiceCertificate),
new RsaSignatureCookieTransform(
e.ServiceConfiguration.ServiceCertificate)
});

// following line is pseudo code. use your own durable cache implementation.
var durableCache = new AppFabricCacheWrapper();

var tokenCache = new DurableSecurityTokenCache(durableCache, 5000);
var sessionHandler = new SessionSecurityTokenHandler(sessionTransforms.AsReadOnly(),
tokenCache,
TimeSpan.FromDays(1));

e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(sessionHandler);
}

private void WSFederationAuthenticationModule_SecurityTokenValidated(object sender, SecurityTokenValidatedEventArgs e)
{
FederatedAuthentication.SessionAuthenticationModule.IsSessionMode = true;
}

DurableSecurityTokenCache.cs:

/// <summary>
/// Two level durable security token cache (level 1: in memory MRU, level 2: out of process cache).
/// </summary>
public class DurableSecurityTokenCache : SecurityTokenCache
{
private ICache<string, byte[]> durableCache;
private readonly MruCache<SecurityTokenCacheKey, SecurityToken> mruCache;

/// <summary>
/// The constructor.
/// </summary>
/// <param name="durableCache">The durable second level cache (should be out of process ie sql server, azure table, app fabric, etc).</param>
/// <param name="mruCapacity">Capacity of the internal first level cache (in-memory MRU cache).</param>
public DurableSecurityTokenCache(ICache<string, byte[]> durableCache, int mruCapacity)
{
this.durableCache = durableCache;
this.mruCache = new MruCache<SecurityTokenCacheKey, SecurityToken>(mruCapacity, mruCapacity / 4);
}

public override bool TryAddEntry(object key, SecurityToken value)
{
var cacheKey = (SecurityTokenCacheKey)key;

// add the entry to the mru cache.
this.mruCache.Add(cacheKey, value);

// add the entry to the durable cache.
var keyString = GetKeyString(cacheKey);
var buffer = this.GetSerializer().Serialize((SessionSecurityToken)value);
this.durableCache.Add(keyString, buffer);

return true;
}

public override bool TryGetEntry(object key, out SecurityToken value)
{
var cacheKey = (SecurityTokenCacheKey)key;

// attempt to retrieve the entry from the mru cache.
value = this.mruCache.Get(cacheKey);
if (value != null)
return true;

// entry wasn't in the mru cache, retrieve it from the app fabric cache.
var keyString = GetKeyString(cacheKey);

var buffer = this.durableCache.Get(keyString);
var result = buffer != null;
if (result)
{
// we had a cache miss in the mru cache but found the item in the durable cache...

// deserialize the value retrieved from the durable cache.
value = this.GetSerializer().Deserialize(buffer);

// push this item into the mru cache.
this.mruCache.Add(cacheKey, value);
}

return result;
}

public override bool TryRemoveEntry(object key)
{
var cacheKey = (SecurityTokenCacheKey)key;

// remove the entry from the mru cache.
this.mruCache.Remove(cacheKey);

// remove the entry from the durable cache.
var keyString = GetKeyString(cacheKey);
this.durableCache.Remove(keyString);

return true;
}

public override bool TryReplaceEntry(object key, SecurityToken newValue)
{
var cacheKey = (SecurityTokenCacheKey)key;

// remove the entry in the mru cache.
this.mruCache.Remove(cacheKey);

// remove the entry in the durable cache.
var keyString = GetKeyString(cacheKey);

// add the new value.
return this.TryAddEntry(key, newValue);
}

public override bool TryGetAllEntries(object key, out IList<SecurityToken> tokens)
{
// not implemented... haven't been able to find how/when this method is used.
tokens = new List<SecurityToken>();
return true;
//throw new NotImplementedException();
}

public override bool TryRemoveAllEntries(object key)
{
// not implemented... haven't been able to find how/when this method is used.
return true;
//throw new NotImplementedException();
}

public override void ClearEntries()
{
// not implemented... haven't been able to find how/when this method is used.
//throw new NotImplementedException();
}

/// <summary>
/// Gets the string representation of the specified SecurityTokenCacheKey.
/// </summary>
private string GetKeyString(SecurityTokenCacheKey key)
{
return string.Format("{0}; {1}; {2}", key.ContextId, key.KeyGeneration, key.EndpointId);
}

/// <summary>
/// Gets a new instance of the token serializer.
/// </summary>
private SessionSecurityTokenCookieSerializer GetSerializer()
{
return new SessionSecurityTokenCookieSerializer(); // may need to do something about handling bootstrap tokens.
}
}

MruCache.cs:

/// <summary>
/// Most recently used (MRU) cache.
/// </summary>
/// <typeparam name="TKey">The key type.</typeparam>
/// <typeparam name="TValue">The value type.</typeparam>
public class MruCache<TKey, TValue> : ICache<TKey, TValue>
{
private Dictionary<TKey, TValue> mruCache;
private LinkedList<TKey> mruList;
private object syncRoot;
private int capacity;
private int sizeAfterPurge;

/// <summary>
/// The constructor.
/// </summary>
/// <param name="capacity">The capacity.</param>
/// <param name="sizeAfterPurge">Size to make the cache after purging because it's reached capacity.</param>
public MruCache(int capacity, int sizeAfterPurge)
{
this.mruList = new LinkedList<TKey>();
this.mruCache = new Dictionary<TKey, TValue>(capacity);
this.capacity = capacity;
this.sizeAfterPurge = sizeAfterPurge;
this.syncRoot = new object();
}

/// <summary>
/// Adds an item if it doesn't already exist.
/// </summary>
public void Add(TKey key, TValue value)
{
lock (this.syncRoot)
{
if (mruCache.ContainsKey(key))
return;

if (mruCache.Count + 1 >= this.capacity)
{
while (mruCache.Count > this.sizeAfterPurge)
{
var lru = mruList.Last.Value;
mruCache.Remove(lru);
mruList.RemoveLast();
}
}
mruCache.Add(key, value);
mruList.AddFirst(key);
}
}

/// <summary>
/// Removes an item if it exists.
/// </summary>
public void Remove(TKey key)
{
lock (this.syncRoot)
{
if (!mruCache.ContainsKey(key))
return;

mruCache.Remove(key);
mruList.Remove(key);
}
}

/// <summary>
/// Gets an item. If a matching item doesn't exist null is returned.
/// </summary>
public TValue Get(TKey key)
{
lock (this.syncRoot)
{
if (!mruCache.ContainsKey(key))
return default(TValue);

mruList.Remove(key);
mruList.AddFirst(key);
return mruCache[key];
}
}

/// <summary>
/// Gets whether a key is contained in the cache.
/// </summary>
public bool ContainsKey(TKey key)
{
lock (this.syncRoot)
return mruCache.ContainsKey(key);
}
}

ICache.cs:

/// <summary>
/// A cache.
/// </summary>
/// <typeparam name="TKey">The key type.</typeparam>
/// <typeparam name="TValue">The value type.</typeparam>
public interface ICache<TKey, TValue>
{
void Add(TKey key, TValue value);
void Remove(TKey key);
TValue Get(TKey key);
}

关于Azure/网络场就绪的 SecurityTokenCache,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8015542/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com