ASP.NET Push Redirect по тайм-ауту сеанса

Я ищу учебник, запись в блоге или некоторую помощь по технике веб-сайтов, которые автоматически подталкивают пользователей (т.е. без обратной передачи) по истечении сеанса. Любая помощь приветствуется


person Michael    schedule 27.01.2009    source источник
comment
Что вы подразумеваете под нажимающими пользователями?   -  person Robert C. Barth    schedule 27.01.2009


Ответы (10)


Обычно вы устанавливаете время ожидания сеанса и можете дополнительно добавить заголовок страницы для автоматического перенаправления текущей страницы на страницу, где вы очищаете сеанс прямо перед временем ожидания сеанса.

Из 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)));
        }
    }
}

SessionExpireDestinationUrl должен ссылаться на страницу, на которой вы очищаете сеанс и любые другие пользовательские данные.

Когда срок действия заголовка обновления истечет, он автоматически перенаправит их на эту страницу.

person TJB    schedule 27.01.2009

Вы не можете «вытолкнуть» клиента с вашего сайта. Ваш сайт будет реагировать на запросы от клиента, но это действительно так.

Это означает, что вам нужно написать что-то на стороне клиента (Javascript), которое будет определять, когда время ожидания пользователя истекло, возможно, путем сравнения текущего времени с самым последним временем, которое он имеет в файле cookie сайта (который вы обновляете текущим раз каждый раз, когда пользователь посещает страницу на вашем сайте), а затем перенаправить, если разница превышает определенную сумму.

(Отмечу, что некоторые люди выступают за то, чтобы просто создать скрипт, который будет перенаправлять пользователя через определенное количество времени на странице. Это будет работать в простом случае, но если у пользователя открыто два окна на сайте, и он использует одно окно много, а другое окно не очень, то не очень, вдруг перенаправит пользователя на страницу переадресации, хотя пользователь был на сайте постоянно.Кроме того, это не совсем синхронно с любой сессией, которую вы делаете на стороне сервера.С другой стороны, это, безусловно, легче кодировать, и если это достаточно хорошо, то отлично!)

person Beska    schedule 27.01.2009

В разделе ‹HEAD> используйте тег обновления META следующим образом:

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

где 0000 – время ожидания сеанса в секундах, а target_page.html – адрес страницы, на которую нужно перенаправить.

person devio    schedule 27.01.2009
comment
Знаешь что? Я люблю тебя за это :) Просто, просто и просто работает, идеально подходит для новичка в asp.net, такого как я :) - person AlexK; 21.05.2015

Используя класс Custom Page и Javascript, мы также можем этого добиться.

Создайте собственный класс pagebase и запишите в него коды общих функций. С помощью этого класса мы можем поделиться общими функциями с другими веб-страницами. В этом классе нам нужно наследовать класс System.Web.UI.Page. Поместите приведенный ниже код в класс 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);
        }
    }
}

Приведенная выше функция AutoRedirect будет использоваться для перенаправления страницы входа по истечении срока действия сеанса с помощью javascript window.setInterval. Этот window.setInterval повторно выполняет функцию javascript с определенной задержкой по времени. Здесь мы настраиваем временную задержку как значение времени ожидания сеанса. По истечении времени истечения сеанса автоматически выполняется функция перенаправления и передача управления на страницу входа.

ИсходныйPage.aspx.cs

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

ИсходныйPage.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>

Примечание. Преимущество использования Javascript заключается в том, что вы можете отображать собственное сообщение в окне предупреждения перед location.href, что будет иметь смысл для пользователя. В случае, если вы не хотите использовать Javascript, вы также можете выбрать мета-перенаправление

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")));
}
person Durai Amuthan.H    schedule 20.02.2014

Просто скопируйте и вставьте этот фрагмент кода в свой файл Web.Config:

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

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

Вы можете поместить эту строку в свой Site.Master :

Response.AppendHeader("Refresh", 
                      Convert.ToString((Session.Timeout * 60)) + 
                      ";URL=~/Login.aspx");
person ersegun    schedule 18.01.2012
comment
Response.AppendHeader(Refresh, Convert.ToString((Session.Timeout * 60)) + ;URL= & System.Web.Security.FormsAuthentication.LoginUrl); - person Jeff Mergler; 17.12.2015

Я использую MVC3 ASp.net как новичок, я пробовал много решений для решения моей проблемы с сеансом (поскольку я использую переменную сеанса в своем коде, и после тайм-аута у меня не было значений сеанса, пока я продолжаю его использовать И Я просто обнаружил, что моя проблема была в файле конфигурации. тайм-аут между Authentication и sessionState должен быть таким близким. поэтому они Killed (пустые) одновременно // добавить тайм-аут 1 и 2 для тестирования.. он должен быть не менее 29 и 30

Я использовал и другие способы работы:

Начиная с :

    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();          
    }

А также :

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

И даже работал с Ajax для решения проблемы сеанса:

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

    }
person Rasha    schedule 27.04.2012

К сожалению, это невозможно сделать. Тайм-аут сеанса происходит только на стороне сервера, и вы не обнаружите это, пока пользователь не выполнит какое-либо действие обратной отправки.

Однако то, что вы МОЖЕТЕ сделать, это внедрить некоторый код заголовка HTML или JavaScript, который автоматически подтолкнет пользователя на страницу выхода в тот же период времени, что и время ожидания вашего сеанса. Это не гарантирует идеальную синхронизацию, и вы можете столкнуться с проблемами, если ваш пользователь выполняет какие-то действия, требующие много времени, а вы не сбрасываете часы.

Я обычно добавляю этот код в свои события Page_Load, чтобы добиться этого.

' 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)
person Dillie-O    schedule 27.01.2009

И если вы используете следующий контроллер входа в систему, он отправит вас на запрошенный URL-адрес перед входом в систему:

   [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);
    }
person Rasha    schedule 27.04.2012

Конечно, вам нужно использовать [Authorize] вместо класса контроллера или даже действия в конкретном случае.

[Authorize]
public class MailController : Controller
{
}
person Rasha    schedule 27.04.2012

Что ж, это становится сложным для запросов AJAX, как указал Заф-Бен Дугид. Вот мое решение, чтобы заставить это работать с AJAX (с использованием веб-элементов управления Telerik, но я полагаю, что они созданы с использованием набора инструментов ASP.NET AJAX).

В двух словах, я свернул свою собственную штуку типа сеанса с скользящим истечением срока действия.

В моем Site.Master я обновляю переменную сеанса при КАЖДОЙ обратной передаче (обратная передача или запрос AJAX, поскольку запросы AJAX по-прежнему запускают событие 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);
    }

Затем в моей разметке для моего site.master я включил iframe со страницей ASPX, которую я использую «за кулисами», чтобы проверить, не истек ли срок действия моего пользовательского скользящего срока действия:

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

Теперь на моей странице SessionExpire.aspx я просто время от времени обновляю страницу и проверяю, истекла ли отметка времени, и если да, то я перенаправляюсь на свою страницу logout.aspx, которая затем определяет, на какую страницу входа отправить пользователя обратно:

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

Большое спасибо людям выше, которые разместили информацию, это привело меня к моему решению и надеюсь, что оно поможет другим.

person Chris Smith    schedule 03.05.2011