[英]With LogOff record in database and deleting cookie behind the Session_End ( ) in Global.asax
我在为期两天的工作中需要帮助。 我正在使用Microsoft C#MVC5技术和框架4.5,还使用带有存储库模式,工作单元和Unity的Entity Framework 6来实现依赖项注入。
我有一个称为AccountController的控制器,该控制器负责在系统上执行登录和注销用户,该控制器通过应用同一构造者的依赖项注入来接收存储库的方法。
public class AccountController : BaseController
{
private readonly IUsuarioApp _usuarioApp;
private readonly IUnitOfWorkAsync _unitOfWorkAsync;
public AccountController() { }
public AccountController(IUsuarioApp usuarioApp, IUnitOfWorkAsync unitOfWorkAsync)
{
_unitOfWorkAsync = unitOfWorkAsync;
_usuarioApp = usuarioApp;
}
// GET: Login
[AllowAnonymous]
public ActionResult Login()
{
return View();
}
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login([Bind(Include = "Email, Password")]LoginViewModel model, string returnUrl)
{
try
{
if (!ModelState.IsValid) return View(model);
var usuarioAutenticado = _usuarioApp.AutenticarUsuarioPor(model.Email, model.Password);
var logDeAcesso = new LogDeAcesso { DataDeAcesso = DateTime.Now, UsuarioId = usuarioAutenticado.Id };
usuarioAutenticado.DataDoUltimoAcesso = logDeAcesso.DataDeAcesso;
_usuarioApp.Update(usuarioAutenticado);
_usuarioApp.GetRepository<LogDeAcesso>().Insert(logDeAcesso);
_unitOfWorkAsync.SaveChanges();
SessionContext.SetAuthenticationToken(usuarioAutenticado.Id.ToString(), false, ConvertToUsuarioViewModel(usuarioAutenticado));
return RedirectToAction("Index", "Home");
}
catch (Exception ex)
{
ModelState.AddModelError("", "Tentativa de login inválido.");
return View(model);
}
}
public ActionResult LogOff(int id)
{
try
{
var ultimoLogsDeAcessoCriado = _usuarioApp.GetRepository<LogDeAcesso>().Query(model => model.UsuarioId == id).OrderBy(model => model.OrderByDescending(c => c.DataDeAcesso)).Select().FirstOrDefault();
if (ultimoLogsDeAcessoCriado == null || ultimoLogsDeAcessoCriado.DataDeSaida != DateTime.MinValue) throw new Exception("Erro ao tentar deslogar do sistema.");
ultimoLogsDeAcessoCriado.DataDeSaida = DateTime.Now;
_usuarioApp.GetRepository<LogDeAcesso>().Update(ultimoLogsDeAcessoCriado);
_unitOfWorkAsync.SaveChanges();
FormsAuthentication.SignOut();
Session.Clear(); //Pode não ser necessário, mas não é problemático o uso como prevenção
Session.Abandon();
//Limpar o cookie de Autenticação
var resetFormsCookie = new HttpCookie(FormsAuthentication.FormsCookieName, "");
resetFormsCookie.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(resetFormsCookie);
//Limpar a session cookie
var resetSessionCookie = new HttpCookie("ASP.NET_SessionId", "");
resetSessionCookie.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(resetSessionCookie);
//Invalida o Cache no lado do Cliente
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();
}
catch (Exception ex)
{
Danger("Error: " + ex.Message);
}
return RedirectToAction("Login", "Account");
}
#region Helpers
private UsuarioViewModel ConvertToUsuarioViewModel(Usuario usuario)
{
return new UsuarioViewModel
{
Id = usuario.Id,
Nome = usuario.Nome,
UltimoAcesso = usuario.DataDoUltimoAcesso
};
}
#endregion
}
被视为登录,通过电子邮件对用户进行身份验证,并创建密码,在访问日志的实例中注册该条目的访问权限,随后创建cookie,该cookie将存储在cookie允许访问应用程序页面的位置。
获得访问权限后,用户可以单击注销按钮,该按钮将启动ActionResult LogOff方法,该方法将基于用户ID获得上次创建日志的访问权限,使用DataDeSaida LogDeAcesso更新数据,清除会话和Cookies,然后将其重定向到登录页面。 如果他再次执行登录,则只能从那里再次访问其他页面。
动态效果是否很好,但是存在问题,并且如果用户没有单击关闭按钮,而是选择关闭选项卡或浏览器? 建立表单后,他将保持20分钟的标准状态(默认情况下,IIS将默认为停机时间),但cookie的过期时间更是如此,更不用说以这种方式,我将无法在LogDeAcesso中注册DataDeSaida。
考虑一下,我在Web.config中配置了Session中的超时间隔
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<globalization culture="pt-BR" uiCulture="pt-BR" />
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" slidingExpiration="true" />
</authentication>
<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
stateNetworkTimeout="20"
sqlConnectionString="data source=127.0.0.1;Integrated Security=SSPI"
sqlCommandTimeout="20"
customProvider=""
cookieless="UseCookies"
cookieName="ASP.NET_SessionId"
timeout="1"
allowCustomSqlDatabase="false"
regenerateExpiredSessionId="true"
partitionResolverType=""
useHostingIdentity="true">
<providers>
<clear />
</providers>
</sessionState>
<machineKey validationKey="466AFE06F664B2E3662F97B81D30E87907F9921E51C95C618A670B396403AD98DD032BCE7610EEAE1FB1DA7B3ED7ACE56537E66FD6DF20E701351697E57C3D9C" decryptionKey="CD10ABC11246E6998AB7B9A8CC142CDD6C8AEF7FB12D15CF12158BEAD647C603" validation="SHA1" decryption="AES" />
</system.web>
</configuration>
仅当发生超时并且使用Global.asax Session_End()
方法时,我才能访问存储库,也不能访问FormsAuthentication
。
我尝试使用以下代码将Session_End()
重定向到ActionResult注销
RouteData routeData = new RouteData();
routeData.Values.Add("controller", "Account");
routeData.Values.Add("action", "Login");
IController AccountMainController = new AccountController();
AccountMainController.Execute(new RequestContext(
new HttpContextWrapper(HttpContext.Current), routeData));
但是,当通过行AccountMainController.Execute(new RequestContext (new HttpContextWrapper(HttpContext.Current), RouteData)); throws an exception of type ArgumentNullException: "Value can not be null Parameter name: httpContext
AccountMainController.Execute(new RequestContext (new HttpContextWrapper(HttpContext.Current), RouteData)); throws an exception of type ArgumentNullException: "Value can not be null Parameter name: httpContext
。
我不知道我该怎么做才能在Session_End()
重复单击注销按钮来执行的操作。 有人可以帮忙吗?
经过大量研究,我得出结论,无法以与单击Session_End()
的按钮时执行的相同方式执行“注销”,在超时事件之后,我安排清除cookie的方式是编写以下代码在Session_Start()
。
protected void Session_Start()
{
try
{
var usuario = new SessionContext().GetUserData();
if (usuario == null) return;
Session.Clear(); //Pode não ser necessário, mas não é problemático o uso como prevenção
Session.Abandon();
//Limpar o cookie de Autenticação
var resetFormsCookie = new HttpCookie(FormsAuthentication.FormsCookieName, "");
resetFormsCookie.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(resetFormsCookie);
//Limpar a session cookie
var resetSessionCookie = new HttpCookie("ASP.NET_SessionId", "");
resetSessionCookie.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(resetSessionCookie);
//Invalida o Cache no lado do Cliente
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();
}
catch (Exception ex)
{
throw ex;
}
finally
{
Response.RedirectToRoute("Default");
}
}
为了预防起见,我在Session_End()
编写了以下代码。
protected void Session_End()
{
Session.Clear();
Session.Abandon();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.