Magento:检测管理员是否在前端页面中登录

25

我创建了一个Magento扩展程序。我想实现对该扩展程序的访问控制。该扩展程序在前端创建了一个页面,我只希望管理员可以访问该页面。因此,我需要一种方法来检测是否在前端页面中已登录管理员。

我尝试了几种解决方案,但似乎都没起作用。

if(Mage::getSingleton('admin/session', array('name' => 'adminhtml'))->isLoggedIn()) echo 'logged in'; else echo 'not logged in';

检查前端是否已登录管理员账户

Mage::getSingleton('core/session', array('name'=>'adminhtml'));
$adminSession = Mage::getSingleton('admin/session');
$adminSession->start();
if ($adminSession->isLoggedIn()) {
   echo 'logged in';
}
12个回答

14

以上解决方案无效!

这里提供一种可行的解决方案(虽然不够优雅,但是在你的应用程序中的任何地方都可以使用,包括phtml视图、模型、控制器或助手!)

$sesId = isset($_COOKIE['adminhtml']) ? $_COOKIE['adminhtml'] : false ;
$session = false;
if($sesId){
    $session = Mage::getSingleton('core/resource_session')->read($sesId);
}
$loggedIn = false;
if($session)
{
    if(stristr($session,'Mage_Admin_Model_User'))
    {
        $loggedIn = true;
    }
}
var_dump($loggedIn);// this will be true if admin logged in and false if not

2
很奇怪,对我完全不起作用,无论如何都报告错误(v 1.7.0.2) - joren
7
这只适用于基于数据库的会话,而不适用于基于文件的会话(PHP默认设置)或其他会话后端,如memcache。 - Fabian Schmengler
2
最好使用session_decode($session); if(Mage::getSingleton('admin/session')->isLoggedIn()) ...,而不是if(stristr($session,'Mage_Admin_Model_User'))... 。这样你实际上正在解码会话信息,而不是依赖于可能被注入到会话数据中的字符串。 - james.c.funk
如何从Magento获取所有已登录的管理员用户? - Naveenbos
我认为没有直接的方法来做到这一点,但是您可以查看magento数据库中的事件日志,找到与用户相关的实体,然后查找已登录但未注销的事件,并将其与cookie寿命进行比较。 - Meabed
显示剩余3条评论

8

有一个新的Magento模块,由Alan Storm编写:https://github.com/astorm/Magento_CrossAreaSessions

$adminhtml  = Mage::getModel('pulsestorm_crossareasession/manager')->getSessionData('adminhtml');

$adminUser = $dataAdminhtml['admin']['user'];
$loggedIn = $adminUser->getId() && $adminUser->getIsActive();

这个解决方案很好,但是如果没有后端用户登录,它会遇到一个错误,因为$adminUsernull,而你尝试在null上执行getId()。我建议在设置$loggedIn之前检查if ($adminUser),否则默认为false - Andreas Schrammel

7

Christoph Peters发布了一条链接,解决了我的问题(在前端页面中检测管理员是否已登录):

//check if adminhtml cookie is set
if(array_key_exists('adminhtml', $_COOKIE)){
   //get session path and add dir seperator and content field of cookie as data name with magento "sess_" prefix
   $sessionFilePath = Mage::getBaseDir('session').DS.'sess_'.$_COOKIE['adminhtml'];
   //write content of file in var
   $sessionFile = file_get_contents($sessionFilePath);

   //save old session
   $oldSession = $_SESSION;
   //decode adminhtml session
   session_decode($sessionFile);
   //save session data from $_SESSION
   $adminSessionData = $_SESSION;
   //set old session back to current session
   $_SESSION = $oldSession;

   if(array_key_exists('user', $adminSessionData['admin'])){
      //save Mage_Admin_Model_User object in var
      $adminUserObj = $adminSessionData['admin']['user'];
      echo 'ADMIN USER IS LOGGED IN';
   }
   else
   {
      echo 'ADMIN USER IS NOT LOGGED IN'
   }
}

非常感谢Christoph Peters!

我尝试了这段代码的许多版本,但只有这个版本适用于我。不知道为什么其他版本都不行,但很高兴现在它可以运行了。非常感谢Christoph Peters! - Wildcard27

3
如果您试图在模板/phtml文件中或块类内部使其工作,那么会很困难。主要是因为Magento(积极地)缓存您的PHTML块以提高性能,从而撤销任何与Cookie检查相关的程序流控制语句。我没有直接/冗长/深入的解释,但这就是我一次又一次遇到的情况。
然而,您的解决方案应该是正确的,但您需要在控制器的preDispatch方法中进行检查,以避免上述侵略性缓存,因为控制器永远不会被缓存。(在您链接的问题中,Nick的解决方案中显示了如何执行此操作。)
// Ensure we're in the admin session namespace for checking the admin user..
Mage::getSingleton('core/session', array('name' => 'adminhtml'))->start();

$admin_logged_in = Mage::getSingleton('admin/session', array('name' => 'adminhtml'))->isLoggedIn();

// ..get back to the original.
Mage::getSingleton('core/session', array('name' => $this->_sessionNamespace))->start();

如果您确实需要在PHTML文件或命名块中执行上述检查,请查看以下代码,了解如何关闭块级缓存并可能使其正常工作。我之前所做的是禁用页脚块的缓存(其中子块,而不是phtml,包含用于检查特定cookie的代码)。
首先,块调用(在local.xml、模块布局更新xml或任何可以进行布局更新的地方找到。我更喜欢将我的自定义内容分成模块,因此模块布局更新xml是最好的选择):
<reference name="footer">      
   <action method="unsetData"><key>cache_lifetime</key></action>
   <action method="unsetData"><key>cache_tags</key></action>
   <block type="newsletterpopup/popup" name="newsletterpopup_footer" template="newsletterpopup/popup.phtml"/>
</reference>

这是newsletterpopup的块类:

<?php
class Launchpad_Newsletterpopup_Block_Popup extends Mage_Core_Block_Template {
    public function canRender() {
         // Check if cookie exists here       
    }
    public function afterRender() { // if block has rendered, this is called.
        // Set cookie, if it doesn't exist here.
    }
}

而phtml可能是这样的:

<?php if($this->canRender()): ?>
   // stuff
<?php endif; ?>

祝你好运!


3

从这里发布的所有解决方案中,有一个是有效的。 在FronAction控制器中使用。 - Deepak Mallah
这是我在这里找到的唯一有效解决方案。我需要在一个 .phtml 文件中进行测试,登录和退出管理员后它能够正确响应。 - Quantum
是的,今天这个代码救了我一命...非常感谢。以下是简化版:如果(array_key_exists('adminhtml', $_COOKIE)){ $sessionFilePath = Mage::getBaseDir('session').DS.'sess_'.$_COOKIE['adminhtml']; $sessionFile = file_get_contents($sessionFilePath); $oldSession = $_SESSION; session_decode($sessionFile); $adminSessionData = $_SESSION; $_SESSION = $oldSession;}如果(array_key_exists('user', $adminSessionData['admin'])){ $adminUserObj = $adminSessionData['admin']['user']; }如果($adminUserObj){ // var_dump($adminUserObj); } else { header("Location: /"); die(); } - Abbey

1
这段代码将会运行。
//get the admin session
Mage::getSingleton('core/session', array('name'=>'adminhtml'));

//verify if the user is logged in to the backend
if(Mage::getSingleton('admin/session')->isLoggedIn()) {
  //do stuff
}
else
{
  echo "404 page not found";
}

或者

$adminsession = Mage::getSingleton('admin/session', array('name'=>'adminhtml'));

if($adminsession->isLoggedIn()) {
    //do stuff
} else {
    echo "404 page not found";
}

你尝试过转储$_SESSION变量吗?也许它能帮助你找到正确的方向。


不行啊,无论是在控制器、模型还是块中都不行。 - Nirmal Ram
我正在使用Community 1.7版本,但它无法正常工作。让我向您解释一下。我创建了一个扩展,该扩展扩展了前端控制器并显示在前端。我只想让管理员可以访问它。 - Nirmal Ram
@NirmalRam ,是的,我发布的代码可以工作,因为我已经开发了这种类型的模块,只有管理员才能访问。你尝试遍历一下 $_SESSION 变量了吗? - Sumit Bijvani
如果你检查了,我已经声明过你发表的答案不起作用。所以请在一个继承了 Mage_Core_Controller_Front_Action 的前端控制器中尝试你所写的内容。 - Nirmal Ram
哦,你没明白我的意思。我是在问你,在使用var_dump函数输出$_SESSION变量时,你得到了哪些值?你有没有得到任何值? - Sumit Bijvani
显示剩余4条评论

1

这很简单,但不是推荐的解决方案。我自己花了好几个小时来做这个。 对于基于Windows的服务器,请尝试以下解决方案:

$sessionFilePath = Mage::getBaseDir('session').DS.'sess_'.$_COOKIE['adminhtml'];
$sessionFile     = file_get_contents($sessionFilePath); 
$exp_cookie   = explode(';',$sessionFile);
if(count($exp_cookie)   >   100)
{
  return "login";
}
return "expire";    

对于基于Linux的服务器,请尝试以下解决方案:
$sessionFilePath = Mage::getBaseDir('session').DS.'sess_'.$_COOKIE['adminhtml'];
$sessionFile     = file_get_contents($sessionFilePath); 
$exp_cookie   = explode('--',$sessionFile)
if(count($exp_cookie)   >   10)
{
  return "login";
}
return "expire";

感谢,Kashif。

1
除了尝试从adminhtml cookie中获取会话id(这可能有效也可能无效,依我看最好只是“美化”需要显示的页面,使其看起来像在前端,并使用管理员控制器,以便在管理员会话下运行。

另一种解决方案是将客户从管理员复制到前端并在访问页面之前登录他们,然后只需要检查已登录的客户是否属于某个组。


谢谢,我已经暂时解决了这个问题。但是我需要我的扩展只能由管理员访问,并且它将在前端中使用。 - Nirmal Ram

0

能够使用的关键:

// Ensure we're in the admin session namespace for checking the admin user..
Mage::getSingleton('core/session', array('name' => 'adminhtml'))->start();

$admin_logged_in = Mage::getSingleton('admin/session', array('name' => 'adminhtml'))->isLoggedIn();

// ..get back to the original.
Mage::getSingleton('core/session', array('name' => $this->_sessionNamespace))->start();

这意味着 controller 必须 extends Mage_Adminhtml_Controller_Action

然后您可以在 preDispatch 函数中使用此代码。

并在 config.xmladmin 部分设置此控制器的 routers


如果控制器扩展了 Mage_Adminhtml_Controller_Action,那我为什么要问这个问题呢?谢谢,但我的控制器扩展了前端控制器,如果我将其扩展到 adminhtml,则会重定向到后端。 - Nirmal Ram
你可以设置路由,使页面看起来像在前端一样(没有 /admin),并扩展 Mage_Adminhtml_Controller_Action。好的,我用这种方法让它工作了。 - user457015

0
require_once $dir.'app/Mage.php';
umask(0);

$apps = Mage::app('default');
Mage ::getSingleton('core/session', array('name'=>'adminhtml'));
$adminSession = Mage::getSingleton('admin/session');
$adminSession->start();
if ($adminSession->isLoggedIn()) {
   //echo "logged in";
} 
 else { 
      //echo "Not logged in";
      exit();
 }?> 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接