我使用带有个人用户帐户的asp.net mvc 5网站模板项目,基于custom session state provider
编写了我自己的entity framework
。
当我启动我的应用程序时,注册一个新的网站用户并登录,除了我手动将一些值设置为UserId
变量之外,没有会话信息(如Session
)存储在数据库表中。在调试我的custom session state provider
后,我可以说它运作良好,但这不是我想要的。
我认为每个网站页面加载都会以唯一的会话ID启动新会话,或者继续当前会话ID,会话ID存储在浏览器cookie中,并通过custom session state provider
写入数据库。我尝试实现这样的应用程序行为,我该如何实现这样的应用程序行为?
经过6个月的努力解决这个问题后,我完全
更新
我想跟踪数据库中的所有会话,甚至是匿名用户的空会话,但只有在我将某些值设置为Session
变量时才会创建新的会话数据库记录。我还需要在密码更改时强制所有计算机/浏览器的注销用户。这是一个复杂的asp.net会话状态机制,我无法理解。
public class WebsiteSessionStateProvider : SessionStateStoreProviderBase
{
WebsiteDbContext m_DbContext;
int m_Timeout;
public WebsiteDbContext DatabaseContext
{
get
{
return m_DbContext ?? HttpContext.Current.GetOwinContext().GetUserManager<WebsiteDbContext>();
}
private set
{
m_DbContext = value;
}
}
public override void Initialize(string name, NameValueCollection config)
{
if (config == null) throw new ArgumentNullException(nameof(config));
base.Initialize(name, config);
var applicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
var configuration = WebConfigurationManager.OpenWebConfiguration(applicationName);
var configSection = (SessionStateSection)configuration.GetSection("system.web/sessionState");
m_Timeout = (int)configSection.Timeout.TotalMinutes;
}
public override void Dispose()
{
}
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
{
return GetSessionItem(context, id, false, out locked, out lockAge, out lockId, out actions);
}
public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
{
return GetSessionItem(context, id, true, out locked, out lockAge, out lockId, out actions);
}
private SessionStateStoreData GetSessionItem(HttpContext context, string id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
{
locked = false;
lockAge = new TimeSpan();
lockId = null;
actions = 0;
var SessionItem = DatabaseContext.Sessions.Find(id);
if (SessionItem == null) return null;
if (SessionItem.IsLocked)
{
locked = true;
lockAge = DateTime.UtcNow - SessionItem.TimeLocked;
lockId = SessionItem.LockId;
return null;
}
if (DateTime.UtcNow > SessionItem.TimeExpires)
{
DatabaseContext.Entry(SessionItem).State = EntityState.Deleted;
DatabaseContext.SaveChanges();
return null;
}
if (exclusive)
{
SessionItem.LockId += 1;
SessionItem.IsLocked = true;
SessionItem.TimeLocked = DateTime.UtcNow;
DatabaseContext.SaveChanges();
}
locked = exclusive;
lockAge = DateTime.UtcNow - SessionItem.TimeLocked;
lockId = SessionItem.LockId;
var data = (SessionItem.Content == null)
? CreateNewStoreData(context, m_Timeout)
: Deserialize(context, SessionItem.Content, m_Timeout);
data.Items["UserId"] = SessionItem.User.Id;
return data;
}
public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
{
var SessionItem = DatabaseContext.Sessions.Find(id);
if (SessionItem.LockId != (int)lockId) return;
SessionItem.IsLocked = false;
SessionItem.TimeExpires = DateTime.UtcNow.AddMinutes(m_Timeout);
DatabaseContext.SaveChanges();
}
public override void SetAndReleaseItemExclusive(HttpContext context,
string id,
SessionStateStoreData item,
object lockId,
bool newItem)
{
var intLockId = lockId == null ? 0 : (int)lockId;
var userId = (string)item.Items["UserId"];
var data = ((SessionStateItemCollection)item.Items);
data.Remove("UserId");
var Content = Serialize(data);
if (newItem)
{
var session = new Session
{
SessionId = id,
User = DatabaseContext.Users.Find(userId),
TimeCreated = DateTime.UtcNow,
TimeExpires = DateTime.UtcNow.AddMinutes(m_Timeout),
TimeLocked = DateTime.UtcNow,
IsLocked = false,
Content = Content,
LockId = 0,
};
DatabaseContext.Sessions.Add(session);
DatabaseContext.SaveChanges();
return;
}
var state = DatabaseContext.Sessions.Find(id);
if (state.LockId == (int)lockId)
{
state.User = DatabaseContext.Users.Find(userId);
state.Content = Content;
state.TimeExpires = DateTime.UtcNow.AddMinutes(m_Timeout);
state.IsLocked = false;
DatabaseContext.SaveChanges();
}
}
public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
{
var state = DatabaseContext.Sessions.Find(id);
if (state.LockId != (int)lockId) return;
DatabaseContext.Entry(state).State = EntityState.Deleted;
DatabaseContext.SaveChanges();
}
public override void ResetItemTimeout(HttpContext context, string id)
{
var SessionItem = DatabaseContext.Sessions.Find(id);
if (SessionItem == null) return;
SessionItem.TimeExpires = DateTime.UtcNow.AddMinutes(m_Timeout);
DatabaseContext.SaveChanges();
}
public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
{
var data = new SessionStateStoreData(new SessionStateItemCollection(),
SessionStateUtility.GetSessionStaticObjects(context),
timeout);
data.Items["UserId"] = String.Empty;
return data;
}
public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
{
var session = new Session
{
SessionId = id,
User = null,
TimeCreated = DateTime.UtcNow,
TimeExpires = DateTime.UtcNow.AddMinutes(timeout),
TimeLocked = DateTime.UtcNow,
IsLocked = false,
Content = null,
LockId = 0,
};
DatabaseContext.Sessions.Add(session);
DatabaseContext.SaveChanges();
}
public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback) { return false; }
public override void EndRequest(HttpContext context) { }
public override void InitializeRequest(HttpContext context) { }
private byte[] Serialize(SessionStateItemCollection items)
{
var ms = new MemoryStream();
var writer = new BinaryWriter(ms);
if (items != null) items.Serialize(writer);
writer.Close();
return ms.ToArray();
}
private SessionStateStoreData Deserialize(HttpContext context, Byte[] serializedItems, int timeout)
{
var ms = new MemoryStream(serializedItems);
var SessionItems = new SessionStateItemCollection();
if (ms.Length > 0)
{
var reader = new BinaryReader(ms);
SessionItems = SessionStateItemCollection.Deserialize(reader);
}
return new SessionStateStoreData(SessionItems, SessionStateUtility.GetSessionStaticObjects(context), timeout);
}
}
答案 0 :(得分:0)
除非我手动将某些值设置为会话变量
,否则没有会话信息(如UserId)存储在数据库表中
这正是会话提供者的用途:从Web应用程序中抽象出会话数据的存储。
如果您未在会话中放置任何内容,则您的提供商不会存储任何内容。