如何防止 Ajax 调用使会话保持活动状态?

Posted

技术标签:

【中文标题】如何防止 Ajax 调用使会话保持活动状态?【英文标题】:How do I prevent Ajax calls from keeping a session alive? 【发布时间】:2014-06-20 23:21:11 【问题描述】:

我在 MVC5 中使用 cookie 身份验证。我的网页严重依赖每 1-5 秒经过身份验证和未经身份验证的 Ajax 调用来保持数据更新。因此,我的用户永远不会退出该站点。

我的理想场景:如果用户正在我的网站上积极浏览或执行操作,请保持会话处于活动状态。如果他们在 10 分钟后打开页面,我希望他们的会话超时,我将使用失败的 Ajax 调用重定向到登录页面。我认为这最好在控制器或操作级别完成。

我尝试按照以下建议控制会话状态行为,但会话仍然没有超时。在每秒点击一次 ReadOnly/Public 65 秒后,我调用 ReadOnly/Authorized 并成功从中检索数据。

这是我的 CookieAuthentication 配置。

public void ConfigureAuth(IAppBuilder app)

    // Enable the application to use a cookie to store information for the signed in user
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login"),
        ExpireTimeSpan = TimeSpan.FromMinutes(1),
    );

我的测试页面:

<div id="public"></div>
<div id="authorized"></div>


@section scripts
<script>

function poll(times) 
    var url = '/ReadOnly/Public';
    $.ajax(
        url: url,
        dataType: 'json',
        data: null,
        cache: false,
        success: function (data) 
            $('#public').html(times + ' ' + data.test);

        ,
        error: function (data) 
            $('#public').html(times + ' ' + 'failed');
        
    );
;

function checkAuth(times) 
    var url = '/ReadOnly/Authorized';
    $.ajax(
        url: url,
        dataType: 'json',
        data: null,
        cache: false,
        success: function (data) 
            $('#authorized').html(times + ' ' + data.test);

        ,
        error: function (data) 
            $('#authorized').html(times + ' ' + 'failed');
        
    );
;

$(function () 
    var times = 1;
    setInterval(function () 
        poll(times);
        times++;
    , 1000);
    setInterval(function () 
        checkAuth(times);
    , 65000);

);
</script>

并测试控制器代码(尝试使用禁用和只读选项)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.SessionState;

namespace SessionTest.Controllers

[SessionState(SessionStateBehavior.ReadOnly)]
public class ReadOnlyController : Controller

    [Authorize]
    public ActionResult Authorized()
    
        return Json(new
        
            test = "ReadOnly and Authorized"
        , JsonRequestBehavior.AllowGet);
    

    public ActionResult Public()
    
        return Json(new
        
            test = "ReadOnly and Public"
        , JsonRequestBehavior.AllowGet);
    


【问题讨论】:

当前实现的表现如何?无论用户做什么,它都会在 10 分钟内退出,还是在用户空闲 10 分钟后退出? 用户从不注销。他们的会话无限期打开,因为 Ajax 调用每 5 秒进行一次,超时窗口为 10 分钟。 你为什么要这样做?如果他们离开网页,或手动注销(我假设该选项仍然存在)会话将终止。如果没有,那一切听起来都很好。我讨厌超时,他们很痛苦。 从用户体验的角度,想想一个金融应用。您想强制执行超时,这样用户就不会离开他们的办公桌,然后他们的钱就会被抽走。从服务器资源的角度来看,如果用户不活跃,我想保留网络和数据库负载。 我遵守规则,帮助那些愿意帮助自己的人。您对授权控制器有一个无限循环,不愿意实现会话状态,并且显然不愿意编写自己的 cookie 提供程序。你祈求奇迹,不愿意与任何人一起满足你的需要。我删除我的答案,祝你好运。 【参考方案1】:

我认为滑动过期默认设置为 true。

我想也许当对动作 Public 进行调用时,它是使用 cookie 进行的,因此会延长超时时间。

    public ActionResult Public()
    
        return Json(new
        
            test = "ReadOnly and Public"
        , JsonRequestBehavior.AllowGet);
    

如果我在下面设置:(SlidingExpiration = false)。我收到失败的消息。

       app.UseCookieAuthentication(new CookieAuthenticationOptions
        
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            ExpireTimeSpan =  TimeSpan.FromMinutes(1.0),
            SlidingExpiration = false
            //Provider = new CookieAuthenticationProvider
            //
            //    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
            //        validateInterval: TimeSpan.FromMinutes(30),
            //        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            //
        );

【讨论】:

我确实检查了这一点,并且我的示例代码设置了缓存标志。 您的 web.config 中有设置来删除 如果是这样,我认为有一个错字应该是 FormsAuthentication 而不是 FormsAuthenticationModule。 不幸的是, 都没有解决问题。会话仍然没有超时。【参考方案2】:

也许您需要拥有 2 个独立的网络应用程序。一种是用于提供经过身份验证的请求。另一种是针对所有公共请求。

这类似于 Google Analytics 脚本如何在 Google 端创建和维护自己的关于您网站的会话,而不会影响您的网络应用程序的内部会话管理。否则,您将受困于 ASP .NET 处理 cookie 和保持会话活动的方式的默认行为。

祝你好运。

【讨论】:

经过大量实验和拉扯头发后,我认为这是我们将要采取的解决方案。感谢所有倾听我令人沮丧的业务需求的人。【参考方案3】:

Ajax 调用将使会话保持活动状态。

一种方法是在客户端设置超时以在一段时间后删除 cookie。 我不确定您是否还有其他选择。

如果每 5 秒调用一次仅针对未经身份验证的请求,则只需将 cookie 排除在 ajax 请求之外。

【讨论】:

【参考方案4】:

我会将侦听器方法或类配置为不使用会话,这会阻止它被扩展。

提供不同会话模式的方法和控制器都有可用的属性。

更多信息在这里: http://www.dotnet-tricks.com/Tutorial/mvc/906b060113-Controlling-Session-Behavior-in-Asp.Net-MVC4.html

【讨论】:

我刚刚测试了这个,会话没有超时。【参考方案5】:

在这种情况下我不会实施超时。事实上,我尽量避免使用它们,除非有必要的基本和关键原因,否则它们只会成为烦恼。

但是,如果您确实需要一个,我会在这种情况下实现它,方法是创建一个具有计时器的单独 javascript 函数,并通过用户输入进行重置。如果计时器完成,则执行 ajax 调用,在服务器端执行手动会话失效。

【讨论】:

以上是关于如何防止 Ajax 调用使会话保持活动状态?的主要内容,如果未能解决你的问题,请参考以下文章

从使用 axios 调用响应启动 php 会话不会使会话保持活动状态,但使用邮递员执行它就可以了

保持 ASP.NET 会话打开/活动

服务器断开连接后如何在 Spring MVC 中保持客户端会话处于活动状态

如何解决会话超时问题?

让会话无限期地保持活跃状态

如何防止模态盒关闭?