Angularjs 会话到期时SPA重新登录

Angularjs 会话到期时SPA重新登录,angularjs,session,single-page-application,Angularjs,Session,Single Page Application,我正在用AngularJS构建一个单页应用程序。我正在考虑两种方法来处理服务器端会话过期的长空闲期 方法A:在AJAX中检测、重新登录、重新发送 用户最初加载应用程序并登录 用户使用应用程序一段时间,然后闲置,保持应用程序打开 服务器端会话过期 用户使用应用程序恢复 当试图保存数据时,angular http拦截器检测到401状态码响应,显示登录模式对话框,如果用户正确验证(从而启动新的服务器端会话),则将更改重新提交给服务器 我认为这在技术上是可能的,但是UX可能有点不协调,实现可能会变得

我正在用AngularJS构建一个单页应用程序。我正在考虑两种方法来处理服务器端会话过期的长空闲期

方法A:在AJAX中检测、重新登录、重新发送
  • 用户最初加载应用程序并登录
  • 用户使用应用程序一段时间,然后闲置,保持应用程序打开
  • 服务器端会话过期
  • 用户使用应用程序恢复
  • 当试图保存数据时,angular http拦截器检测到401状态码响应,显示登录模式对话框,如果用户正确验证(从而启动新的服务器端会话),则将更改重新提交给服务器
我认为这在技术上是可能的,但是UX可能有点不协调,实现可能会变得复杂,因为可能有多种类型的AJAX请求触发401响应(单击链接、编辑字段等)

方法B:跟踪客户端上的空闲时间并提示重新登录
  • 用户最初加载应用程序并登录
  • 用户使用应用程序一段时间,然后闲置,保持应用程序打开
  • 在每个服务器响应上,浏览器代码启动一个空闲计时器
  • 当服务器交互时间超过会话到期时间时,浏览器会优先显示登录模式对话框
  • 用户返回,看到对话框,可以在继续使用应用程序之前登录
我认为这种方法可能是一种更好的用户体验,而且实现起来也更简单,因为没有重试逻辑



这两个选项中有一个是可靠的吗?有更好的方法吗?

好吧,每种方法都有其优点和缺点,但我使用混合方法来获得这两种方法的优点,同时也抛弃缺点。我的方法的核心是,在服务器端有一个过滤器来更新每个请求的会话信息(过期、有效期),但客户端也会根据用户与UI的交互定期发送keepalive请求。每个keep-alive都从服务器返回一个响应,该响应指示会话仍然有效(不会通过从另一个选项卡注销或通过SSO而失效)。你需要记住的事情:

  • 方法1本身是不够的,因为用户考虑阅读文本和滚动和点击周围的活动。所以,如果您的客户端功能连接到单击(例如显示弹出窗口)中,而该单击并没有向服务器发送Ajax调用,则即使用户一直单击该按钮,也会注销该用户

  • 方法2本身也是不够的,因为您只依赖当前用户选项卡上的用户活动(除非您使用浏览器存储),而不依赖服务器数据。由此引发的问题是a)用户在另一个选项卡上注销,但仍在另一个选项卡上登录b)在许多安全情况下,您需要使用单一登录将应用程序嵌入到第三方应用程序中,然后只要用户在另一个应用程序中处于活动状态,您就需要有效地登录

  • 绝对接近A。 但更优雅的方法是使用
    $httpProvider.interceptors

    Angular应用程序启动后,按如下方式配置应用程序:

    app.config(['$httpProvider', function ($httpProvider) {
        $httpProvider.interceptors.push(['$q', function ($q) {
            return {
                'responseError': function (rejection) {
                    if (rejection.status === 440) {//I prefer to use 440 to indicate the user is timeout.
                        //window.location.href = "/login"; redirect to your login page
                    }
                    return $q.reject(rejection);
                }
            };
        }]);
    }]);
    
    通过这样做,可以将重定向方法注入到$http的方法中。任何时候,如果服务器发回
    440
    代码,将首先执行此方法