簡體   English   中英

在數據庫中注銷日志並在Global.asax中的Session_End()后面刪除cookie

[英]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的控制器,該控制器負責在系統上執行登錄和注銷用戶,該控制器通過應用同一構造者的依賴項注入來接收存儲庫的方法。

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中的超時間隔

Web配置

&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));

但是,當通過行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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM