Pergunta

Estou procurando um tutorial, entrada no blog ou alguma ajuda na técnica por trás de sites que empurram automaticamente os usuários (ou seja, sem um postback) quando a sessão expirar. Qualquer ajuda é apreciada

Foi útil?

Solução

Geralmente, você define o tempo limite da sessão e adicionalmente pode adicionar um cabeçalho de página para redirecionar automaticamente a página atual para uma página em que você limpa a sessão logo antes do tempo limite da sessão.

A partir de http://aspalliance.com/1621_implementing_a_session_timeout_page_in_aspnet.2

namespace SessionExpirePage
{
    public partial class Secure : System.Web.UI.MasterPage
    {
        public int SessionLengthMinutes
        {
            get { return Session.Timeout; }
        }
        public string SessionExpireDestinationUrl
        {
            get { return "/SessionExpired.aspx"; }
        }
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            this.PageHead.Controls.Add(new LiteralControl(
                String.Format("<meta http-equiv='refresh' content='{0};url={1}'>", 
                SessionLengthMinutes*60, SessionExpireDestinationUrl)));
        }
    }
}

O SessionExPiredestinationUrl deve vincular a uma página em que você limpa a sessão e quaisquer outros dados do usuário.

Quando o cabeçalho da atualização expirar, ele os redireciona automaticamente para essa página.

Outras dicas

Você não pode realmente "empurrar" um cliente do seu site. Seu site responderá às solicitações do cliente, mas é isso mesmo.

O que isso significa é que você precisa escrever algo do lado do cliente (JavaScript) que determinará quando o usuário tem o tempo limitado, provavelmente comparando o horário atual com o tempo mais recente que eles têm em um cookie de site (que você atualiza com o atual Tempo cada vez que o usuário visita uma página no seu site) e depois redireciona se a diferença for maior que uma certa quantidade.

(Observo que algumas pessoas estão advogando apenas criando um script que encaminhará o usuário após um certo período de tempo em uma página. Isso funcionará no caso simples, mas se o usuário tiver duas janelas abertas no site e estiver usando Uma janela muito, e a outra janela não tão mundial, a não muito tão muito redirecionará o usuário para a página de encaminhamento, mesmo que o usuário esteja no site constantemente. Além disso, não está realmente sincronizado Com qualquer sessão que você esteja fazendo no lado do servidor. Por outro lado, é certamente mais fácil codificar e, se isso for bom o suficiente, é ótimo!)

Nou003CHEAD> Seção, use uma tag meta de atualização como esta:

<meta http-equiv="refresh" content="0000; URL=target_page.html">

onde 0000 é o tempo limite da sessão em segundos e Target_Page.html o endereço da página a ser redirecionado.

Usando a classe de página personalizada e o JavaScript também podemos alcançá -lo.

Crie uma classe de base de página personalizada e escreva os códigos de funcionalidade comuns nessa classe. Através desta classe, podemos compartilhar as funções comuns com outras páginas da web. Nesta classe, precisamos herdar o System.web.ui.page classe. Coloque o código abaixo na classe PageBase

PageBase.CS

namespace AutoRedirect
{
    public class PageBase : System.Web.UI.Page
    {
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            AutoRedirect();
        }

        public void AutoRedirect()
        {
            int int_MilliSecondsTimeOut = (this.Session.Timeout * 60000);
            string str_Script = @"
               <script type='text/javascript'> 
                   intervalset = window.setInterval('Redirect()'," +
                       int_MilliSecondsTimeOut.ToString() + @");
                   function Redirect()
                   {
                       window.location.href='/login.aspx'; 
                   }
               </script>";

           ClientScript.RegisterClientScriptBlock(this.GetType(), "Redirect", str_Script);
        }
    }
}

Acima de Função automática será usado para redirecionar a página de login quando a sessão expirar, usando javascript window.setInterval, Essa janela.setInterval executa uma função JavaScript repetidamente com atraso de tempo específico. Aqui estamos configurando o atraso de tempo como valor de tempo limite da sessão. Uma vez atingido o tempo de expiração da sessão, executa automaticamente a função de redirecionamento e a transferência de controle para a página de login.

OriginalPage.aspx.cs

namespace appStore
{
    public partial class OriginalPage: Basepage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
        }     
    }
}

OriginalPage.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="OriginalPage.aspx.cs" Inherits="AutoRedirect.OriginalPage" %>

Web.config

<system.web>    
    <sessionState mode="InProc" timeout="3"></sessionState>
</system.web>

Nota: A vantagem de usar o JavaScript é que você pode mostrar a mensagem personalizada na caixa de alerta antes do local.href, que fará todo o sentido para o usuário. Caso você não quiser usar o JavaScript, poderá escolher meta redirecionamento também

public void AutoRedirect()
{
    this.Header.Controls.Add(new LiteralControl(
        String.Format("<meta http-equiv='refresh' content='{0};url={1}'>",
            this.Session.Timeout * 60, "login.aspx")));
}

Estou usando o MVC3 ASP.NET como iniciante, tentei muitas soluções para resolver meu problema de sessão (já que estou usando a variável de sessão no meu código e, após o tempo limite, não tive valores de sessão enquanto continuo usando e Eu apenas acho que meu problema estava no arquivo de configuração. O tempo limite entre autenticação e sessionState deveria estar tão próximo. Então eles mataram (vazios) ao mesmo tempo // Adicionar o tempo limite 1 e 2 para testar. Deve ter pelo menos 29 anos e 30

Eu usei outras pessoas como é trabalho também:

Começando de :

    protected void Session_Start(object src, EventArgs e)
    {
        if (Context.Session != null)
        {
            if (Context.Session.IsNewSession)//|| Context.Session.Count==0)
            {
                string sCookieHeader = Request.Headers["Cookie"];
                if ((null != sCookieHeader) && (sCookieHeader.IndexOf("ASP.NET_SessionId") >= 0))
                {
                    //if (Request.IsAuthenticated)
                     FormsAuthentication.SignOut();
                     Response.Redirect("/Account/LogOn");
                }
            }
        }

    }

    protected void Session_End(object sender, EventArgs e)
    {
     //Code that runs when a session ends. 
     //Note: The Session_End event is raised only when the sessionstate mode 
     //is set to InProc in the Web.config file. If session mode is set to StateServer
      //or SQLServer, the event is not raised. 
        Session.Clear();          
    }

E :

public class SessionExpireFilterAttribute : ActionFilterAttribute
{

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        HttpContext ctx = HttpContext.Current;

        // check if session is supported
        if (ctx.Session != null)
        {

            // check if a new session id was generated
            if (ctx.Session.IsNewSession)
            {
                // If it says it is a new session, but an existing cookie exists, then it must
                // have timed out
                string sessionCookie = ctx.Request.Headers["Cookie"];
                if ((null != sessionCookie) && (sessionCookie.IndexOf("ASP.NET_SessionId") >= 0))
                {
                    ctx.Response.Redirect("~/Home/LogOn");
                }
            }
        }

        base.OnActionExecuting(filterContext);
    }
}

E até trabalhou com o Ajax para resolver a sessão Issuse:

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (Session.Count == 0 || Session["CouncilID"] == null)
            Response.Redirect("/Account/LogOn");

        if (Request.IsAjaxRequest() && (!Request.IsAuthenticated || User == null))
        {
            filterContext.RequestContext.HttpContext.Response.StatusCode = 401;
        }
        else
        {
            base.OnActionExecuting(filterContext);
        }
    }

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class AuthorizeUserAttribute : AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (!httpContext.Request.IsAjaxRequest())
            {//validate http request.
                if (!httpContext.Request.IsAuthenticated
                    || httpContext.Session["User"] == null)
                {
                    FormsAuthentication.SignOut();
                    httpContext.Response.Redirect("~/?returnurl=" + httpContext.Request.Url.ToString());
                    return false;
                }
            }
            return true;
        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.Result = new JsonResult
                {
                    Data = new
                    {
                        // put whatever data you want which will be sent
                        // to the client
                        message = "sorry, but you were logged out"
                    },
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                };
            }
            else
            {
                base.HandleUnauthorizedRequest(filterContext);
            }
        }

    }

Basta copiar e colar este snippet de código no seu arquivo web.config:

<authentication mode="Forms">
  <forms loginUrl="~/Login.aspx" slidingExpiration="true" timeout="29" />
</authentication>

<sessionState timeout="30" mode="InProc" cookieless="false" />

Você pode colocar esta linha no seu site.master:

Response.AppendHeader("Refresh", 
                      Convert.ToString((Session.Timeout * 60)) + 
                      ";URL=~/Login.aspx");

Infelizmente, isso não pode ser feito. O tempo limite da sessão ocorre apenas no lado do servidor e você não detectará isso até que o usuário execute algum tipo de ação postal.

No entanto, o que você pode fazer é injetar algum código de cabeçalho HTML ou JavaScript que levará automaticamente o usuário a uma página de logout no mesmo período que o tempo limite da sessão. Isso não garante uma sincronização perfeita e você pode ter problemas se o usuário estiver fazendo algum tempo intensivo itens e você não estiver redefinindo o relógio.

Normalmente, adiciono esse código aos meus eventos Page_load para fazer isso.

' Register Javascript timeout event to redirect to the login page after inactivity
  Page.ClientScript.RegisterStartupScript(Me.GetType, "TimeoutScript", _
                                              "setTimeout(""top.location.href = 'Login.aspx'""," & _
                                               ConfigurationManager.AppSettings("SessionTimeoutMilliseconds") & ");", True)

E se você usar o seguinte controlador de logon, ele o enviará para o URL solicitado antes do logon:

   [HttpPost]
    public ActionResult LogOn(LogOnModel model, string returnUrl)
    {

        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {

                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);

                if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                    && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                {
                    //return Redirect(returnUrl);
                    if (!String.IsNullOrEmpty(returnUrl))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                      return RedirectToAction("Index", "Home");
                    }

                }
                else
                {
                    return RedirectToAction("Index", "Home");
                }
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

Claro que você precisa usar [Authorize] sobre a classe do controlador ou mesmo uma ação específica.

[Authorize]
public class MailController : Controller
{
}

Bem, isso fica complicado para solicitações de Ajax como Zhaph - Ben Duguid apontou. Aqui estava minha solução para fazer isso funcionar com o Ajax (usando os controles da Web Telerik, mas eles são construídos usando o ASP.NET AJAX Toolkit, acredito).

Em poucas palavras, enrolei minha própria coisa do tipo de sessão de vencimento deslizante.

No meu site.master, estou atualizando uma variável de sessão em cada postback (solicitação de postback ou Ajax porque as solicitações de AJAX ainda iniciam o evento Page_load):

protected void Page_Load(object sender, EventArgs e)
    {
        if (!this.IsPostBack)
        {
            if (this.Request.IsAuthenticated)
                this.pnlSessionKeepAlive.Visible = true;
            else
                this.pnlSessionKeepAlive.Visible = false;
        }

        if (this.Session["SessionStartDateTime"] != null)
            this.Session["SessionStartDateTime"] = DateTime.Now;
        else
            this.Session.Add("SessionStartDateTime", DateTime.Now);
    }

Então, na minha marcação para o meu site.master, incluí um iframe com uma página ASPX que eu uso "nos bastidores" para verificar e ver se minha expiração de deslizamento personalizada expirou:

<asp:Panel runat="server" ID="pnlSessionKeepAlive" Visible="false">
 <iframe id="frame1" runat="server" src="../SessionExpire.aspx" frameborder="0" width="0" height="0" / >
 </asp:Panel>

Agora, na minha página sessionExpire.aspx, apenas atualizo a página de vez em quando e verifico se o registro de data e hora e, em caso afirmativo, redireciono para a minha página de logout.aspx que determina qual página de login para enviar o usuário de volta para:

public partial class SessionExpire : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        /* We have to do all of this because we need to redirect to 2 different login pages. The default .NET
         * implementation does not allow us to specify which page to redirect expired sessions, its a fixed value.
         */
        if (this.Session["SessionStartDateTime"] != null)
        {
            DateTime StartTime = new DateTime();
            bool IsValid = DateTime.TryParse(this.Session["SessionStartDateTime"].ToString(), out StartTime);
            if (IsValid)
            {
                int MaxSessionTimeout = Convert.ToInt32(ConfigurationManager.AppSettings["SessionKeepAliveMins"]);
                IsValid = (DateTime.Now.Subtract(StartTime).TotalMinutes < MaxSessionTimeout);
            }

            // either their session expired or their sliding session timeout has expired. Now log them out and redirect to the correct
            // login page.
            if (!IsValid)
                this.Logout();
        }
        else
            this.Logout();

        // check every 60 seconds to see if the session has expired yet.
        Response.AddHeader("Refresh", Convert.ToString(60));
    }

    private void Logout()
    {
        this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "TimeoutScript",
                    "setTimeout(\"top.location.href = '../Public/Logout.aspx'\",\"1000\");", true);
    }
}

Muito obrigado às pessoas acima que postaram informações, isso me levou à minha solução e espero que ajude os outros.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top