会话过期时重定向无法正常工作
Redirection does not work properly when the session expires
我在 Asp.Net MVC 5 和 C# 中有一个项目,并使用自定义 session state customizing SessionStateStoreProviderBase class in Oracle, like this example。我的问题是,当会话过期时,屏幕会变成空白页,只有当用户按下 F5 时,才会第二次加载登录屏幕。只有按两次 f5 后,它才能工作。
有没有人遇到过这个错误?
更新
这是使用的class
public class ProvedorSessao : SessionStateStoreProviderBase
{
private SessionStateSection _pConfig;
private string _connectionString;
private ConnectionStringSettings _pConnectionStringSettings;
private const string EventSource = "AgpSessionDataProvider";
private const string EventLog = "Application";
private const string ExceptionMessage = "SessionCustom - Ocorreu um erro interno na sessão.";
private const int Timeout = 1; //One minute in test app default is 60
private bool _pWriteExceptionsToEventLog;
private bool WriteExceptionsToEventLog => _pWriteExceptionsToEventLog;
private string ApplicationName { get; set; }
public override void Initialize(string name, NameValueCollection config)
{
try
{
if (name.Length == 0)
name = "PortalCustomSessionProvider";
if (String.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "Session State Store provider");
}
base.Initialize(name, config);
ApplicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
Configuration cfg = WebConfigurationManager.OpenWebConfiguration(ApplicationName);
_pConfig = (SessionStateSection)cfg.GetSection("system.web/sessionState");
_pConnectionStringSettings = ConfigurationManager.ConnectionStrings[config["connectionStringName"]];
if (_pConnectionStringSettings == null || _pConnectionStringSettings.ConnectionString.Trim() == "")
{
throw new ProviderException("A string de conexão não pode ser vazia.");
}
_connectionString = "MyStringConection"; //My String Conection oracle
_pWriteExceptionsToEventLog = true;
if (config["writeExceptionsToEventLog"] != null)
{
if (config["writeExceptionsToEventLog"].ToUpper() == "TRUE")
_pWriteExceptionsToEventLog = true;
}
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "Initialize");
throw new ProviderException(ExceptionMessage);
}
throw new Exception(e.Message);
}
}
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
{
//Serializar o SessionStateItemCollection como uma string.
var sessItems = Serialize((SessionStateItemCollection)item.Items);
var conn = new OracleConnection(_connectionString);
OracleCommand cmd;
OracleCommand deleteCmd = null;
if (newItem)
{
deleteCmd = new OracleCommand("DELETE FROM Sessions WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName AND Expires < :Expires", conn);
deleteCmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
deleteCmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
deleteCmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now;
// Insere um novo item na sessão.
cmd = new OracleCommand("INSERT INTO Sessions " +
"(SessionId, ApplicationName, Created, Expires, " +
"LockDate, LockId, Timeout, Locked, SessionItems, Flags, UsuarioId, Menuid) " +
"Values(:SessionId, :ApplicationName, :Created, :Expires, :LockDate, :LockId, :Timeout, :Locked, :SessionItems, :Flags, :UsuarioId, :Menuid)", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.Parameters.Add("Created", OracleDbType.Date).Value = DateTime.Now;
cmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now.AddMinutes(item.Timeout);
cmd.Parameters.Add("LockDate", OracleDbType.Date).Value = DateTime.Now;
cmd.Parameters.Add("LockId", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("Timeout", OracleDbType.Int32).Value = item.Timeout;
cmd.Parameters.Add("Locked", OracleDbType.Int32).Value = Convert.ToInt32(false);
cmd.Parameters.Add("SessionItems", OracleDbType.Varchar2, sessItems.Length).Value = sessItems;
cmd.Parameters.Add("Flags", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("UsuarioId", OracleDbType.Varchar2, 50).Value = "";
cmd.Parameters.Add("Menuid", OracleDbType.Varchar2, 50).Value = "";
}
else
{
var usuarioid = "";
var menuid = "";
if (item.Items != null)
{
usuarioid = string.IsNullOrEmpty(item.Items["codUsuario"] + "")
? ""
: item.Items["codUsuario"].ToString();
menuid = string.IsNullOrEmpty(item.Items["codMenu"] + "")
? ""
: item.Items["codMenu"].ToString();
}
cmd = new OracleCommand("UPDATE Sessions SET Expires = :Expires, SessionItems = :SessionItems, Locked = :Locked, usuarioid = :usuarioid, menuid = :menuid " +
" WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName AND LockId = :LockId", conn);
cmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now.AddMinutes(item.Timeout);
cmd.Parameters.Add("SessionItems", OracleDbType.Varchar2, sessItems.Length).Value = sessItems;
cmd.Parameters.Add("Locked", OracleDbType.Int32).Value = Convert.ToInt32(false);
cmd.Parameters.Add("usuarioid", OracleDbType.Varchar2, 50).Value = usuarioid;
cmd.Parameters.Add("menuid", OracleDbType.Varchar2, 50).Value = menuid;
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.Parameters.Add("LockId", OracleDbType.Int32).Value = lockId;
}
try
{
conn.Open();
deleteCmd?.ExecuteNonQuery();
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "SetAndReleaseItemExclusive");
throw new ProviderException(ExceptionMessage);
}
else
{
throw new Exception(e.Message);
}
}
finally
{
conn.Close();
}
}
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
{
return GetSessionStoreItem(false, context, id, out locked, out lockAge, out lockId, out actionFlags);
}
public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
{
return GetSessionStoreItem(true, context, id, out locked, out lockAge, out lockId, out actionFlags);
}
private SessionStateStoreData GetSessionStoreItem(bool lockRecord, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
{
//Valores iniciais de retorno e parâmetros de saída.
SessionStateStoreData item = null;
lockAge = TimeSpan.Zero;
lockId = null;
locked = false;
actionFlags = 0;
var conn = new OracleConnection(_connectionString); //Conexão com o banco
OracleDataReader reader = null;
var serializedItems = ""; //Variável para armazenar serialização SessionStateItemCollection.
var foundRecord = false; //True se um registro for encontrado na base de dados.
var deleteData = false; //True se o item de sessão retornou expirou e precisa ser eliminado.
var timeout = 0; //Valor do tempo limite de armazenamento de dados.
try
{
conn.Open();
// LockRecord se for True é chamado de GetItemExclusive e
// falso se for chamado de GetItem.
// Obtem um bloqueio, se possível. Ignorar o Registro se elemento expirou.
OracleCommand cmd;
if (lockRecord)
{
cmd = new OracleCommand(
"UPDATE Sessions SET" +
" Locked = :Locked1, LockDate = :LockDate " +
" WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName AND Locked = :Locked2 AND Expires > :Expires", conn);
cmd.Parameters.Add("Locked1", OracleDbType.Int32).Value = Convert.ToInt32(true);
cmd.Parameters.Add("LockDate", OracleDbType.Date).Value = DateTime.Now;
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.Parameters.Add("Locked2", OracleDbType.Int32).Value = Convert.ToInt32(false);
cmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now;
locked = cmd.ExecuteNonQuery() == 0;
}
cmd = new OracleCommand(
"SELECT Expires, SessionItems, LockId, LockDate, Flags, Timeout, Locked, usuarioid, menuid " +
"FROM Sessions " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
while (reader.Read())
{
DateTime expires = reader.GetDateTime(0);
if (expires < DateTime.Now)
{
locked = false; //O registro foi expirado. Marca como não locked.
deleteData = true; //O registro foi deletado. Marca como deletado.
}
else
foundRecord = true;
serializedItems = reader.IsDBNull(1) ? "" : reader.GetString(1);
lockId = reader.IsDBNull(2) ? 0 : Convert.ToInt32(reader[2]);
lockAge = DateTime.Now.Subtract(reader.GetDateTime(3));
actionFlags = (SessionStateActions)(reader.IsDBNull(4) ? 0 : Convert.ToInt32(reader[4]));
timeout = reader.IsDBNull(5) ? 60 : Convert.ToInt32(reader[5]);
if (!lockRecord)
locked = reader.GetBoolean(7);
}
reader.Close();
if (deleteData)
{
cmd = new OracleCommand("DELETE FROM Sessions " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.ExecuteNonQuery();
}
if (!foundRecord)
locked = false;
if (foundRecord && !locked)
{
lockId = (int)lockId + 1;
cmd = new OracleCommand("UPDATE Sessions SET " +
"LockId = :LockId, Flags = 0 " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("LockId", OracleDbType.Int32).Value = lockId;
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.ExecuteNonQuery();
switch (actionFlags)
{
case SessionStateActions.InitializeItem:
item = CreateNewStoreData(context, (int)_pConfig.Timeout.TotalMinutes);
break;
default:
item = Deserialize(context, serializedItems, timeout);
break;
}
}
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetSessionStoreItem");
throw new ProviderException(ExceptionMessage);
}
else
{
throw new Exception(e.Message);
}
}
finally
{
reader?.Close();
conn.Close();
}
return item;
}
private string Serialize(SessionStateItemCollection items)
{
var ms = new MemoryStream();
var writer = new BinaryWriter(ms);
items?.Serialize(writer);
writer.Close();
return Convert.ToBase64String(ms.ToArray());
}
private SessionStateStoreData Deserialize(HttpContext context, string serializedItems, int timeout)
{
var ms = new MemoryStream(Convert.FromBase64String(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);
}
public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
{
var conn = new OracleConnection(_connectionString);
var cmd = new OracleCommand("UPDATE Sessions SET Locked = 0, Expires = :Expires " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName AND LockId = :LockId", conn);
cmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now.AddMinutes(_pConfig.Timeout.TotalMinutes);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.Parameters.Add("LockId", OracleDbType.Int32).Value = lockId;
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "ReleaseItemExclusive");
throw new ProviderException(ExceptionMessage);
}
else
{
throw new Exception(e.Message);
}
}
finally
{
conn.Close();
}
}
public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
{
var conn = new OracleConnection(_connectionString);
var cmd = new OracleCommand("DELETE FROM Sessions " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName AND LockId = :LockId", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.Parameters.Add("LockId", OracleDbType.Int32).Value = lockId;
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "RemoveItem");
throw new ProviderException(ExceptionMessage);
}
else
{
throw new Exception(e.Message);
}
}
finally
{
conn.Close();
}
}
public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
{
var conn = new OracleConnection(_connectionString);
var cmd = new OracleCommand("INSERT INTO Sessions " +
"(SessionId, ApplicationName, Created, Expires, " +
"LockDate, LockId, Timeout, Locked, SessionItems, Flags, UsuarioId, Menuid) " +
"Values(:SessionId, :ApplicationName, :Created, :Expires, :LockDate, :LockId, :Timeout, :Locked, :SessionItems, :Flags, :UsuarioId, :Menuid)", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.Parameters.Add("Created", OracleDbType.Date).Value = DateTime.Now;
cmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now.AddMinutes(timeout);
cmd.Parameters.Add("LockDate", OracleDbType.Date).Value = DateTime.Now;
cmd.Parameters.Add("LockId", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("Timeout", OracleDbType.Int32).Value = timeout;
cmd.Parameters.Add("Locked", OracleDbType.Int32).Value = Convert.ToInt32(false);
cmd.Parameters.Add("SessionItems", OracleDbType.Varchar2).Value = "";
cmd.Parameters.Add("Flags", OracleDbType.Int32).Value = 1;
cmd.Parameters.Add("UsuarioId", OracleDbType.Varchar2, 50).Value = "";
cmd.Parameters.Add("Menuid", OracleDbType.Varchar2, 50).Value = "";
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "CreateUninitializedItem");
throw new ProviderException(ExceptionMessage);
}
else
{
throw new Exception(e.Message);
}
}
finally
{
conn.Close();
cmd.Dispose();
}
}
public override SessionStateStoreData CreateNewStoreData(HttpContext context, int i)
{
return new SessionStateStoreData(new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), Timeout);
}
public override void ResetItemTimeout(HttpContext context, string id)
{
var conn = new OracleConnection(_connectionString);
var cmd = new OracleCommand("UPDATE Sessions SET Expires = :Expires " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now.AddMinutes(_pConfig.Timeout.TotalMinutes);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "ResetItemTimeout");
throw new ProviderException(ExceptionMessage);
}
else
{
throw new Exception(e.Message);
}
}
finally
{
conn.Close();
}
}
public override void InitializeRequest(HttpContext context)
{
if (context != null)
{
if (context.Request.Cookies.Count <= 0) return;
//Verifica se a sessão é nula
if (context.Request.Cookies["ASP.NET_SessionId"] == null) return;
OracleDataReader reader = null;
var conn = new OracleConnection(_connectionString); //Get connection
try
{
var expireData = false;
var id = context.Request.Cookies["ASP.NET_SessionId"].Value; //get session id cookie
//Conexão com o banco
conn.Open();
//get data session oracle
var cmd = new OracleCommand("SELECT Expires, SessionItems, LockId, LockDate, Flags, Timeout, Locked, usuarioid, menuid " + "FROM Sessions " + "WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
//Recupera dados da sessão da fonte de dados.
reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
while (reader.Read())
{
//Se estiver expirado marca flag true
DateTime expires = reader.GetDateTime(0);
if (expires < DateTime.Now)
{
expireData = true;
}
}
if (expireData)
{
cmd = new OracleCommand("DELETE FROM Sessions " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.ExecuteNonQuery();
context.Response.End();
}
}
catch (HttpException)
{
//Força httpexception caso não funcione
}
catch (Exception e)
{
//Se der erro generico da classe grava log e não prossegue dando throw exception
throw new Exception(e.Message);
}
finally
{
//Finaliza as conexões e objetos
reader?.Close();
conn.Close();
}
}
}
public override void EndRequest(HttpContext context)
{
//Não utilizado...
}
private static void WriteToEventLog(Exception e, string action)
{
//var log = new EventLog { Source = EventSource, Log = EventLog };
if (!System.Diagnostics.EventLog.SourceExists(EventSource))
System.Diagnostics.EventLog.CreateEventSource(EventSource, EventLog);
var message = "Ocorreu um erro ao tentar comunicação com o banco de dados.\n\n";
message += "Ação: " + action + "\n\n";
message += "Exceção: " + e;
System.Diagnostics.EventLog.WriteEntry(EventSource, message);
//log.WriteEntry(message);
}
public override void Dispose()
{
//Não utilizado
}
public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
{
return true;
}
}
不知道是不是这个class问题
谢谢
我发现了我的问题。在 inicializeRequest 方法中没有强制重定向到登录屏幕的操作。然后我添加了以下命令并且它起作用了。我不知道这是否是最好的方法,但它奏效了。
throw new HttpException((int)HttpStatusCode.Unauthorized, "Error Session, not authorized.");
inicializerequest 中的代码块也是如此:
if (expireData)
{
cmd = new OracleCommand("DELETE FROM Sessions " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.ExecuteNonQuery();
throw new HttpException((int)HttpStatusCode.Unauthorized, "Error session, not authorized");
context.Response.End();
}
我不知道这是否是最好的方法,但如果他们愿意帮助我改进我的代码,我将不胜感激。谢谢
我在 Asp.Net MVC 5 和 C# 中有一个项目,并使用自定义 session state customizing SessionStateStoreProviderBase class in Oracle, like this example。我的问题是,当会话过期时,屏幕会变成空白页,只有当用户按下 F5 时,才会第二次加载登录屏幕。只有按两次 f5 后,它才能工作。
有没有人遇到过这个错误?
更新
这是使用的class
public class ProvedorSessao : SessionStateStoreProviderBase
{
private SessionStateSection _pConfig;
private string _connectionString;
private ConnectionStringSettings _pConnectionStringSettings;
private const string EventSource = "AgpSessionDataProvider";
private const string EventLog = "Application";
private const string ExceptionMessage = "SessionCustom - Ocorreu um erro interno na sessão.";
private const int Timeout = 1; //One minute in test app default is 60
private bool _pWriteExceptionsToEventLog;
private bool WriteExceptionsToEventLog => _pWriteExceptionsToEventLog;
private string ApplicationName { get; set; }
public override void Initialize(string name, NameValueCollection config)
{
try
{
if (name.Length == 0)
name = "PortalCustomSessionProvider";
if (String.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "Session State Store provider");
}
base.Initialize(name, config);
ApplicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
Configuration cfg = WebConfigurationManager.OpenWebConfiguration(ApplicationName);
_pConfig = (SessionStateSection)cfg.GetSection("system.web/sessionState");
_pConnectionStringSettings = ConfigurationManager.ConnectionStrings[config["connectionStringName"]];
if (_pConnectionStringSettings == null || _pConnectionStringSettings.ConnectionString.Trim() == "")
{
throw new ProviderException("A string de conexão não pode ser vazia.");
}
_connectionString = "MyStringConection"; //My String Conection oracle
_pWriteExceptionsToEventLog = true;
if (config["writeExceptionsToEventLog"] != null)
{
if (config["writeExceptionsToEventLog"].ToUpper() == "TRUE")
_pWriteExceptionsToEventLog = true;
}
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "Initialize");
throw new ProviderException(ExceptionMessage);
}
throw new Exception(e.Message);
}
}
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
{
//Serializar o SessionStateItemCollection como uma string.
var sessItems = Serialize((SessionStateItemCollection)item.Items);
var conn = new OracleConnection(_connectionString);
OracleCommand cmd;
OracleCommand deleteCmd = null;
if (newItem)
{
deleteCmd = new OracleCommand("DELETE FROM Sessions WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName AND Expires < :Expires", conn);
deleteCmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
deleteCmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
deleteCmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now;
// Insere um novo item na sessão.
cmd = new OracleCommand("INSERT INTO Sessions " +
"(SessionId, ApplicationName, Created, Expires, " +
"LockDate, LockId, Timeout, Locked, SessionItems, Flags, UsuarioId, Menuid) " +
"Values(:SessionId, :ApplicationName, :Created, :Expires, :LockDate, :LockId, :Timeout, :Locked, :SessionItems, :Flags, :UsuarioId, :Menuid)", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.Parameters.Add("Created", OracleDbType.Date).Value = DateTime.Now;
cmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now.AddMinutes(item.Timeout);
cmd.Parameters.Add("LockDate", OracleDbType.Date).Value = DateTime.Now;
cmd.Parameters.Add("LockId", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("Timeout", OracleDbType.Int32).Value = item.Timeout;
cmd.Parameters.Add("Locked", OracleDbType.Int32).Value = Convert.ToInt32(false);
cmd.Parameters.Add("SessionItems", OracleDbType.Varchar2, sessItems.Length).Value = sessItems;
cmd.Parameters.Add("Flags", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("UsuarioId", OracleDbType.Varchar2, 50).Value = "";
cmd.Parameters.Add("Menuid", OracleDbType.Varchar2, 50).Value = "";
}
else
{
var usuarioid = "";
var menuid = "";
if (item.Items != null)
{
usuarioid = string.IsNullOrEmpty(item.Items["codUsuario"] + "")
? ""
: item.Items["codUsuario"].ToString();
menuid = string.IsNullOrEmpty(item.Items["codMenu"] + "")
? ""
: item.Items["codMenu"].ToString();
}
cmd = new OracleCommand("UPDATE Sessions SET Expires = :Expires, SessionItems = :SessionItems, Locked = :Locked, usuarioid = :usuarioid, menuid = :menuid " +
" WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName AND LockId = :LockId", conn);
cmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now.AddMinutes(item.Timeout);
cmd.Parameters.Add("SessionItems", OracleDbType.Varchar2, sessItems.Length).Value = sessItems;
cmd.Parameters.Add("Locked", OracleDbType.Int32).Value = Convert.ToInt32(false);
cmd.Parameters.Add("usuarioid", OracleDbType.Varchar2, 50).Value = usuarioid;
cmd.Parameters.Add("menuid", OracleDbType.Varchar2, 50).Value = menuid;
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.Parameters.Add("LockId", OracleDbType.Int32).Value = lockId;
}
try
{
conn.Open();
deleteCmd?.ExecuteNonQuery();
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "SetAndReleaseItemExclusive");
throw new ProviderException(ExceptionMessage);
}
else
{
throw new Exception(e.Message);
}
}
finally
{
conn.Close();
}
}
public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
{
return GetSessionStoreItem(false, context, id, out locked, out lockAge, out lockId, out actionFlags);
}
public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
{
return GetSessionStoreItem(true, context, id, out locked, out lockAge, out lockId, out actionFlags);
}
private SessionStateStoreData GetSessionStoreItem(bool lockRecord, HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags)
{
//Valores iniciais de retorno e parâmetros de saída.
SessionStateStoreData item = null;
lockAge = TimeSpan.Zero;
lockId = null;
locked = false;
actionFlags = 0;
var conn = new OracleConnection(_connectionString); //Conexão com o banco
OracleDataReader reader = null;
var serializedItems = ""; //Variável para armazenar serialização SessionStateItemCollection.
var foundRecord = false; //True se um registro for encontrado na base de dados.
var deleteData = false; //True se o item de sessão retornou expirou e precisa ser eliminado.
var timeout = 0; //Valor do tempo limite de armazenamento de dados.
try
{
conn.Open();
// LockRecord se for True é chamado de GetItemExclusive e
// falso se for chamado de GetItem.
// Obtem um bloqueio, se possível. Ignorar o Registro se elemento expirou.
OracleCommand cmd;
if (lockRecord)
{
cmd = new OracleCommand(
"UPDATE Sessions SET" +
" Locked = :Locked1, LockDate = :LockDate " +
" WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName AND Locked = :Locked2 AND Expires > :Expires", conn);
cmd.Parameters.Add("Locked1", OracleDbType.Int32).Value = Convert.ToInt32(true);
cmd.Parameters.Add("LockDate", OracleDbType.Date).Value = DateTime.Now;
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.Parameters.Add("Locked2", OracleDbType.Int32).Value = Convert.ToInt32(false);
cmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now;
locked = cmd.ExecuteNonQuery() == 0;
}
cmd = new OracleCommand(
"SELECT Expires, SessionItems, LockId, LockDate, Flags, Timeout, Locked, usuarioid, menuid " +
"FROM Sessions " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
while (reader.Read())
{
DateTime expires = reader.GetDateTime(0);
if (expires < DateTime.Now)
{
locked = false; //O registro foi expirado. Marca como não locked.
deleteData = true; //O registro foi deletado. Marca como deletado.
}
else
foundRecord = true;
serializedItems = reader.IsDBNull(1) ? "" : reader.GetString(1);
lockId = reader.IsDBNull(2) ? 0 : Convert.ToInt32(reader[2]);
lockAge = DateTime.Now.Subtract(reader.GetDateTime(3));
actionFlags = (SessionStateActions)(reader.IsDBNull(4) ? 0 : Convert.ToInt32(reader[4]));
timeout = reader.IsDBNull(5) ? 60 : Convert.ToInt32(reader[5]);
if (!lockRecord)
locked = reader.GetBoolean(7);
}
reader.Close();
if (deleteData)
{
cmd = new OracleCommand("DELETE FROM Sessions " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.ExecuteNonQuery();
}
if (!foundRecord)
locked = false;
if (foundRecord && !locked)
{
lockId = (int)lockId + 1;
cmd = new OracleCommand("UPDATE Sessions SET " +
"LockId = :LockId, Flags = 0 " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("LockId", OracleDbType.Int32).Value = lockId;
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.ExecuteNonQuery();
switch (actionFlags)
{
case SessionStateActions.InitializeItem:
item = CreateNewStoreData(context, (int)_pConfig.Timeout.TotalMinutes);
break;
default:
item = Deserialize(context, serializedItems, timeout);
break;
}
}
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "GetSessionStoreItem");
throw new ProviderException(ExceptionMessage);
}
else
{
throw new Exception(e.Message);
}
}
finally
{
reader?.Close();
conn.Close();
}
return item;
}
private string Serialize(SessionStateItemCollection items)
{
var ms = new MemoryStream();
var writer = new BinaryWriter(ms);
items?.Serialize(writer);
writer.Close();
return Convert.ToBase64String(ms.ToArray());
}
private SessionStateStoreData Deserialize(HttpContext context, string serializedItems, int timeout)
{
var ms = new MemoryStream(Convert.FromBase64String(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);
}
public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
{
var conn = new OracleConnection(_connectionString);
var cmd = new OracleCommand("UPDATE Sessions SET Locked = 0, Expires = :Expires " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName AND LockId = :LockId", conn);
cmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now.AddMinutes(_pConfig.Timeout.TotalMinutes);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.Parameters.Add("LockId", OracleDbType.Int32).Value = lockId;
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "ReleaseItemExclusive");
throw new ProviderException(ExceptionMessage);
}
else
{
throw new Exception(e.Message);
}
}
finally
{
conn.Close();
}
}
public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
{
var conn = new OracleConnection(_connectionString);
var cmd = new OracleCommand("DELETE FROM Sessions " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName AND LockId = :LockId", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.Parameters.Add("LockId", OracleDbType.Int32).Value = lockId;
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "RemoveItem");
throw new ProviderException(ExceptionMessage);
}
else
{
throw new Exception(e.Message);
}
}
finally
{
conn.Close();
}
}
public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
{
var conn = new OracleConnection(_connectionString);
var cmd = new OracleCommand("INSERT INTO Sessions " +
"(SessionId, ApplicationName, Created, Expires, " +
"LockDate, LockId, Timeout, Locked, SessionItems, Flags, UsuarioId, Menuid) " +
"Values(:SessionId, :ApplicationName, :Created, :Expires, :LockDate, :LockId, :Timeout, :Locked, :SessionItems, :Flags, :UsuarioId, :Menuid)", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.Parameters.Add("Created", OracleDbType.Date).Value = DateTime.Now;
cmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now.AddMinutes(timeout);
cmd.Parameters.Add("LockDate", OracleDbType.Date).Value = DateTime.Now;
cmd.Parameters.Add("LockId", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("Timeout", OracleDbType.Int32).Value = timeout;
cmd.Parameters.Add("Locked", OracleDbType.Int32).Value = Convert.ToInt32(false);
cmd.Parameters.Add("SessionItems", OracleDbType.Varchar2).Value = "";
cmd.Parameters.Add("Flags", OracleDbType.Int32).Value = 1;
cmd.Parameters.Add("UsuarioId", OracleDbType.Varchar2, 50).Value = "";
cmd.Parameters.Add("Menuid", OracleDbType.Varchar2, 50).Value = "";
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "CreateUninitializedItem");
throw new ProviderException(ExceptionMessage);
}
else
{
throw new Exception(e.Message);
}
}
finally
{
conn.Close();
cmd.Dispose();
}
}
public override SessionStateStoreData CreateNewStoreData(HttpContext context, int i)
{
return new SessionStateStoreData(new SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), Timeout);
}
public override void ResetItemTimeout(HttpContext context, string id)
{
var conn = new OracleConnection(_connectionString);
var cmd = new OracleCommand("UPDATE Sessions SET Expires = :Expires " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("Expires", OracleDbType.Date).Value = DateTime.Now.AddMinutes(_pConfig.Timeout.TotalMinutes);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
if (WriteExceptionsToEventLog)
{
WriteToEventLog(e, "ResetItemTimeout");
throw new ProviderException(ExceptionMessage);
}
else
{
throw new Exception(e.Message);
}
}
finally
{
conn.Close();
}
}
public override void InitializeRequest(HttpContext context)
{
if (context != null)
{
if (context.Request.Cookies.Count <= 0) return;
//Verifica se a sessão é nula
if (context.Request.Cookies["ASP.NET_SessionId"] == null) return;
OracleDataReader reader = null;
var conn = new OracleConnection(_connectionString); //Get connection
try
{
var expireData = false;
var id = context.Request.Cookies["ASP.NET_SessionId"].Value; //get session id cookie
//Conexão com o banco
conn.Open();
//get data session oracle
var cmd = new OracleCommand("SELECT Expires, SessionItems, LockId, LockDate, Flags, Timeout, Locked, usuarioid, menuid " + "FROM Sessions " + "WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
//Recupera dados da sessão da fonte de dados.
reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
while (reader.Read())
{
//Se estiver expirado marca flag true
DateTime expires = reader.GetDateTime(0);
if (expires < DateTime.Now)
{
expireData = true;
}
}
if (expireData)
{
cmd = new OracleCommand("DELETE FROM Sessions " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.ExecuteNonQuery();
context.Response.End();
}
}
catch (HttpException)
{
//Força httpexception caso não funcione
}
catch (Exception e)
{
//Se der erro generico da classe grava log e não prossegue dando throw exception
throw new Exception(e.Message);
}
finally
{
//Finaliza as conexões e objetos
reader?.Close();
conn.Close();
}
}
}
public override void EndRequest(HttpContext context)
{
//Não utilizado...
}
private static void WriteToEventLog(Exception e, string action)
{
//var log = new EventLog { Source = EventSource, Log = EventLog };
if (!System.Diagnostics.EventLog.SourceExists(EventSource))
System.Diagnostics.EventLog.CreateEventSource(EventSource, EventLog);
var message = "Ocorreu um erro ao tentar comunicação com o banco de dados.\n\n";
message += "Ação: " + action + "\n\n";
message += "Exceção: " + e;
System.Diagnostics.EventLog.WriteEntry(EventSource, message);
//log.WriteEntry(message);
}
public override void Dispose()
{
//Não utilizado
}
public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
{
return true;
}
}
不知道是不是这个class问题
谢谢
我发现了我的问题。在 inicializeRequest 方法中没有强制重定向到登录屏幕的操作。然后我添加了以下命令并且它起作用了。我不知道这是否是最好的方法,但它奏效了。
throw new HttpException((int)HttpStatusCode.Unauthorized, "Error Session, not authorized.");
inicializerequest 中的代码块也是如此:
if (expireData)
{
cmd = new OracleCommand("DELETE FROM Sessions " +
"WHERE SessionId = :SessionId AND ApplicationName = :ApplicationName", conn);
cmd.Parameters.Add("SessionId", OracleDbType.Varchar2, 80).Value = id;
cmd.Parameters.Add("ApplicationName", OracleDbType.Varchar2, 255).Value = ApplicationName;
cmd.ExecuteNonQuery();
throw new HttpException((int)HttpStatusCode.Unauthorized, "Error session, not authorized");
context.Response.End();
}
我不知道这是否是最好的方法,但如果他们愿意帮助我改进我的代码,我将不胜感激。谢谢