在数据库中有LogOff记录,并在Global.asax中删除Session_End()后面的cookie

本文关键字:End cookie Session asax LogOff 数据库 记录 Global 并在 删除 | 更新日期: 2023-09-27 18:26:07

我在一个项目中需要帮助,我两天来都在崩溃。我使用的是微软的C#MVC5技术和框架4.5,还使用实体框架6与存储库模式、工作单元和Unity来实现依赖注入。

我有一个名为AccountController的控制器,负责在系统上执行登录和注销用户,该控制器通过相同的Construtor应用依赖注入来接收存储库的方法。

会计总监

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更新数据,清除会话和Cookie,将其重定向到登录页面。从那里,如果他再次登录,他将只能再次访问其他页面。

动态是否工作得很好,但有问题,如果用户不点击关闭按钮,而是关闭选项卡或浏览器?表单建立后,他将保持登录20分钟标准IIS默认为停机时间,但cookie的过期时间,更不用说这样我就无法在LogDeAcesso中注册DataDeSaida了。

考虑到这一点,我在Web.config中配置了会话中的超时间隔

Web.Config

&ltconfiguration&gt
    &ltsystem.web&gt
        &ltcompilation debug="true" targetFramework="4.5" /&gt
        &lthttpRuntime targetFramework="4.5" /&gt
        &ltglobalization culture="pt-BR" uiCulture="pt-BR" /&gt
        &ltauthentication mode="Forms"&gt
            &ltforms loginUrl="~/Account/Login" timeout="2880" slidingExpiration="true" /&gt
        &lt/authentication&gt
        &ltsessionState
            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"&gt
            &ltproviders&gt
                &ltclear /&gt
            &lt/providers&gt
        &lt/sessionState&gt
        &ltmachineKey validationKey="466AFE06F664B2E3662F97B81D30E87907F9921E51C95C618A670B396403AD98DD032BCE7610EEAE1FB1DA7B3ED7ACE56537E66FD6DF20E701351697E57C3D9C" decryptionKey="CD10ABC11246E6998AB7B9A8CC142CDD6C8AEF7FB12D15CF12158BEAD647C603" validation="SHA1" decryption="AES" /&gt 
    &lt/system.web&gt
&lt/configuration&gt

只有当超时发生并且我使用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));

然而当通过线路CCD_ 4。

我想知道我必须做些什么才能在Session_End()中重复单击注销按钮所做的操作。有人能帮忙吗?

在数据库中有LogOff记录,并在Global.asax中删除Session_End()后面的cookie

经过大量研究,我得出结论,不可能像在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();
    }