代码之家  ›  专栏  ›  技术社区  ›  Andrew Flanagan

ASP.NET MVC会话过期

  •  14
  • Andrew Flanagan  · 技术社区  · 15 年前

    我们有一个需要登录的内部ASP.NET MVC应用程序。登录的工作很好,做什么是预期的。我们有15分钟的时间。在一个页面上坐了一段时间后,用户失去了会话。如果他们试图刷新当前页面或浏览到另一个页面,他们将在页面上获得一个日志。我们会保存他们的请求,以便他们登录后可以继续访问他们请求的页面。这很有效。

    然而,我的问题是在某些页面上有AJAX调用。例如,他们可能会填写表单的一部分,然后离开,让他们的会话过期。当他们回来时,屏幕仍然显示。如果他们只是填写一个框(这将进行AJAX调用),AJAX调用将返回登录页(在AJAX应该返回实际结果的任何div中)。这看起来很可怕。

    我认为解决方案是使页面本身过期(这样当会话终止时,它们会自动返回到登录屏幕,而无需执行任何操作)。但是,我想知道是否有关于如何最好地实现这一点的意见/想法,特别是关于ASP.NETMVC中的最佳实践。

    OnActionExecuting (根据Keltex的建议)

      if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
      {
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
          filterContext.HttpContext.Response.Write("Invalid session -- please login!");
          filterContext.HttpContext.Response.End();
        }
        else
        {
          ...
        }
      }
    

    这无疑会让事情变得更好——现在即使他们有两个选项卡(其中一个带有一些可以触发的AJAX调用)并在第二个选项卡中显式注销,他们也会立即得到更有意义的东西,而不是一堆乱七八糟的AJAX数据。

    我仍然认为我将实现womp建议的Javascript倒计时。

    6 回复  |  直到 15 年前
        1
  •  16
  •   womp    15 年前

    5分钟前,我们弹出一个模式对话框,上面写着“你还在吗?”还有一个倒计时计时器。一旦计时器到达0:00,我们将浏览器重定向到登录页面。

    它是用最少的javascript来实现时间和计时器计算的,还有一个简单的.ashx处理程序,如果用户单击“我回来了”,它将刷新会话在会话到期之前。这样,如果它们及时返回,就可以刷新会话而无需任何导航。

        2
  •  7
  •   LukLed    15 年前

    昨天我问了类似的问题。以下是我的解决方案:

    修改的授权属性:

    public class OptionalAuthorizeAttribute : AuthorizeAttribute
    {
        private class Http403Result : ActionResult
        {
            public override void ExecuteResult(ControllerContext context)
            {
                // Set the response code to 403.
                context.HttpContext.Response.StatusCode = 403;
                context.HttpContext.Response.Write(CTRes.AuthorizationLostPleaseLogOutAndLogInAgainToContinue);
            }
        }
    
        private readonly bool _authorize;
    
        public OptionalAuthorizeAttribute()
        {
            _authorize = true;
        }
    
        //OptionalAuthorize is turned on on base controller class, so it has to be turned off on some controller. 
        //That is why parameter is introduced.
        public OptionalAuthorizeAttribute(bool authorize)
        {
            _authorize = authorize;
        }
    
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            //When authorize parameter is set to false, not authorization should be performed.
            if (!_authorize)
                return true;
    
            var result = base.AuthorizeCore(httpContext);
    
            return result;
        }
    
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
            {
                //Ajax request doesn't return to login page, it just returns 403 error.
                filterContext.Result = new Http403Result();
            }
            else
                base.HandleUnauthorizedRequest(filterContext);
        }
    }
    

    HandleUnauthorizedRequest Http403Result 当使用Ajax时。 http403结果 authorize 参数),因为我打开 [Authorize] 并在某些页面中禁用它。

    另一个重要部分是在客户端对这个响应的全局处理。这是我放在网站上的东西。大师:

    <script type="text/javascript">
        $(document).ready(
            function() {
                $("body").ajaxError(
                    function(e,request) {
                        if (request.status == 403) {
                            alert(request.responseText);
                            window.location = '/Logout';
                        }
                    }
                );
            }
        );
    </script>
    

    我放置全局ajax错误处理程序 $.post 失败,出现403错误,响应消息被警告,用户被重定向到注销页面。现在我不必每次都处理错误了 $邮政 请求,因为它是全局处理的。

    为什么是403,而不是401?401由MVC框架在内部处理(这就是为什么在授权失败后重定向到登录页)。

    你觉得怎么样?

    编辑:

    关于从[Authorize]辞职属性:[Authorize]不仅仅是关于检查身份。IsAuthenticated。它还处理页面缓存(这样就不会缓存需要身份验证的内容)和重定向。无需复制此代码。

        3
  •  2
  •   Dave Swersky    15 年前

    window.location .

        4
  •  1
  •   Keltex    15 年前

    [Authorize] 属性。而是检查 User.Identity.IsAuthenticated 如果返回false,则创建可感知的错误消息。

        5
  •  0
  •   OzrenTkalcecKrznaric    11 年前

    <html>
      <head>
        <meta data-name="__loginform__" content="true" />
        ...
      </head>
      ...
    </html>
    

    通用.js

    var Common = {
        IsLoginForm: function (data) {
            var res = false;
    
            if (data.indexOf("__loginform__") > 0) {
                // Do a meta-test for login form
                var temp =
                    $("<div>")
                        .html(data)
                        .find("meta[data-name='__loginform__']")
                        .attr("content");
    
                res = !!temp;
            }
            return res;
        }
    };
    

    AJAX代码

    $.get(myUrl, myData, function (serverData) {
        if (Common.IsLoginForm(serverData)) {
            location.reload();
            return;
        }
    
        // Proceed with filling your placeholder or whatever you do with serverData response
        // ...
    });
    
        6
  •  -1
  •   m0r6aN    9 年前

    在我的基地控制器

     protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                if (filterContext.HttpContext.Request.IsAjaxRequest())
                {
                    filterContext.HttpContext.Response.StatusCode = 403;
                    filterContext.HttpContext.Response.Write(SessionTimeout);
                    filterContext.HttpContext.Response.End();
                }
            }
        }
    

    然后在我的global.js文件中

    $.ajaxSetup({
    error: function (x, status, error) {
        if (x.status == 403) {
            alert("Sorry, your session has expired. Please login again to continue");
            window.location.href = "/Account/Login";
        }
        else {
            alert("An error occurred: " + status + "nError: " + error);
        }
    }
    

    });

    SessionTimeout变量是noty字符串。为了简洁起见,我省略了实现。