【问题标题】:Zend Framework Automatic Logout after inactivityZend Framework 不活动后自动注销
【发布时间】:2012-02-20 04:03:53
【问题描述】:

我正在开发一个包含多个子应用程序的应用程序,我想在 30 分钟不活动后实现自动注销。我有一个使用 Bootstrap.php 的登录和注销操作映射到自定义 /login 和 /logout 路由的 AuthController 以及一个如下所示的前端控制器插件:

class Plugin_SessionTrack extends Zend_Controller_Plugin_Abstract {

    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {  

        $employeeSession = new Zend_Session_Namespace('employeeSession');
        $employeeSession->setExpirationSeconds(10);

    }
}

我是 PHP 和 Zend 的新手,10 秒后会话到底发生了什么?我把它设置得很低以进行测试。我希望发生的情况是,如果通过前端控制器插件的最后一次请求的时间超过 30 分钟,则销毁会话并将用户注销并将其重定向到 /login。

我可以清楚地看到我没有跟踪上次请求的时间,但我希望每次用户通过此 preDispatch 方法收到请求时都会刷新 setExpirationSeconds。

也许需要使用 cookie?我不需要实际启动注销操作,它可以在用户下次发出请求时处理,如果他们在过去半小时内没有做任何事情,则会话被破坏并且他们被注销,这意味着如果我离开 45 分钟,我的屏幕看起来还是一样,但是如果我单击链接或尝试提交我已经准备好的表格,它会将我发送到 /login。以后我可以担心某种类型的 JS 倒计时警告。

编辑:如果有人想看,这是我的引导程序:

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    /**
     * Custom routes:
     * 
     * /login
     * /logout
     */
    protected function _initRoutes()
    {

        $router = Zend_Controller_Front::getInstance()->getRouter();

        $loginRoute = new Zend_Controller_Router_Route('login', array('controller' => 'auth', 'action' => 'login'));

        $logoutRoute = new Zend_Controller_Router_Route('logout', array('controller' => 'auth', 'action' => 'logout'));

        $routesArray = array('login' => $loginRoute, 'logout' => $logoutRoute);

        $router->addRoutes($routesArray);

    }

    protected function _initPlugins()
    {

        $frontController = Zend_Controller_Front::getInstance();
        $frontController->registerPlugin(new Plugin_SessionTrack());

    }
}

【问题讨论】:

  • 首先定义“不活动”。我们在 php 中看到的只是服务器请求。我真的很讨厌这个建议,但是您可能想使用 javascript 来监视活动,并在它“超时”时调用注销方法。命名空间过期似乎无法满足您的需求。
  • 不活动意味着用户没有发布表单,他们没有在控制器中点击操作。基本上他们是“远离键盘”。这所房子的子应用程序是非常数据驱动的,因此如果事情没有影响控制器(操作),它们应该很明显没有使用该应用程序。

标签: php zend-framework session


【解决方案1】:

当您致电Zend_Session::setExpirationSeconds(10) 时,会话本身在 10 秒后实际上没有发生任何事情。

此调用导致 Zend_Session 存储一个内部值,该值标记该会话命名空间从调用时起在time() + $seconds 到期。每次Zend_Session 启动时,它都会检查是否有任何会话数据被标记为过期,如果是,则继续检查过期时间或跳数是否已过。如果是这种情况,则相关会话数据在初始化时未设置,因此您的应用程序无法再访问。

如果您在每个请求开始时进行此调用,它应该会在每次页面加载时继续将会话的生命周期延长那么多秒。

请记住,如果php.ini 中的会话设置设置为会话在 15 分钟后过期,则将命名空间设置为在 60 分钟后过期不会覆盖 PHP 的 15 分钟会话生命周期。您可以在 application.ini 文件中对 PHP 的会话指令进行此类调整。

在命名空间上设置过期还具有自动删除一些会话数据而无需销毁整个会话的优点。

我不知道您的应用程序的具体情况,但您可以使用该插件检查并查看他们是否已注销并将请求转发到您的登录页面。您可以在创建命名空间后检查有效登录,但您还需要确保当前请求不是登录尝试。或者您可以推迟检查插件中的有效登录,然后让您的 ACL 稍后在控制器级别处理。

您可能还想查看Zend_Auth,您可以使用它在会话中保持身份。身份可以是任何东西,从指示他们是否登录的简单布尔值到实现Zend_Acl_Role_Interface 的完整用户对象。 Zend Auth 也很容易扩展,因此您可以通过为每个实例使用不同的名称空间来同时激活多个 Zend_Auth 会话,并且可以让您的自定义身份验证类对不同的会话名称空间设置不同的时间限制。

我希望这有助于回答您的问题,如果您对我所说的内容有任何疑问,请随时发表评论。

编辑:

我测试了以下代码,它在设定的时间后成功地使我的 Zend_Auth 身份过期。我用 60 秒对其进行了低测试,在等待 60 秒加载页面后,我不再拥有身份并被“注销”。您可以将其添加到您的会话跟踪插件中。

<?php
$auth = Zend_Auth::getInstance();

if ($auth->hasIdentity()) { // user is logged in
    // get an instance of Zend_Session_Namespace used by Zend_Auth
    $authns = new Zend_Session_Namespace($auth->getStorage()->getNamespace());

    // set an expiration on the Zend_Auth namespace where identity is held
    $authns->setExpirationSeconds(60 * 30);  // expire auth storage after 30 min
}

【讨论】:

  • gist.github.com/8b2ae80e23543a34ca8a 这是我的登录操作。我正在使用 Zend_Auth 适配器通过 Active Directory 对它们进行身份验证。如果他们在网站上执行的最后一次操作是 > 30 分钟前,我可以强制注销他们的用户。
  • 稍后在您的应用程序中,您如何检查用户是否已登录?您是否只是检查身份验证的身份是否为空?请参阅我更新的答案,其中显示了如何使 Zend_Auth 身份过期。希望这就是您想要的。
  • 是的,稍后如果我需要查看他们是否已登录,我只需获取 getIdentity() 并查看它的外观。那么当将 $authns 设置为在 30 分钟内过期时,这是否会使之前良好的 getIdentity() 变为 null?
  • 是的,一旦命名空间过期,他们就不再有身份了;它将返回 null,hasIdentity() 将返回 false。
  • 宾果游戏!将 $auth->getStorage()->getNamespace() 传递给 Zend_Session_Namespace 是关键。谢谢!
猜你喜欢
  • 2017-06-20
  • 2016-11-03
  • 2013-01-12
  • 1970-01-01
  • 2011-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
相关资源
最近更新 更多