为什么覆盖密码散列会导致 url 在 magento 管理中中断?

Why has overriding password hashing caused urls to break in magento admin?

我在自定义模块中覆盖了 Mage_Core_Model_Encryptionhash($data)validateHash($password, $hash)。它有效,我可以使用我的密码登录到管理区域,并使用新的哈希值正确验证;但是,我无法在管理区域中导航。我看到类似密码的散列成为 url 的一部分: admin/dashboard/index/key/[bcrypt hash here]。浏览器无法重定向到生成的 url。谁能建议我在不破坏 url 的情况下覆盖密码哈希?提前致谢。

如果有帮助,我的配置 xml 如下所示:

<?xml version="1.0" ?>
<config>
  <modules>
    <Mycompany_Encryption>
      <version>0.1</version>
      <depends>Mage_Core</depends>
    </Mycompany_Encryption>
  </modules>
  <global>
    <models>
      <core>
        <rewrite>
          <encryption>Mycompany_Encryption_Model_Encryption</encryption>
        </rewrite>
      </core>
    </models>
    <helpers>
      <core>
        <encryption_model>Mycompany_Encryption_Model_Encryption</encryption_model>
      </core>
    </helpers>
  </global>
</config>

更新::(根据下面的两条评论)如何使用 password_hash 而不是 md5 进行密码验证,同时允许 url 密钥使用url 友好的哈希函数?

我对核心文件做了一些研究,看起来通过工厂可以实现你想要实现的目标。

遗憾的是,看起来 Magento 完成了部分工作,但不是全部。

Mage_Core_Model_Encryption::_getCrypt($key = null)

protected function _getCrypt($key = null)
{
    if (!$this->_crypt) {
        if (null === $key) {
            $key = (string)Mage::getConfig()->getNode('global/crypt/key');
        }
        $this->_crypt = Varien_Crypt::factory()->init($key);
    }
    return $this->_crypt;
}

Varien_Crypt 这让我说这还没有完全完成,那是一个工厂,但在上面的函数中调用时没有参数,所以,是的,没办法改变工厂返回的对象,唉。

class Varien_Crypt
{
    static public function factory($method='mcrypt')
    {
        $uc = str_replace(' ','_',ucwords(str_replace('_',' ',$method)));
        $className = 'Varien_Crypt_'.$uc;
        return new $className;
    }
}

但是知道这两个是这样设计的,您可以:重写 Varien_Crypt 以实例化另一个 class 并基于 class Varien_Crypt_Mcrypt 的方法,实施相同的方法并获得您想要实现的目标。

通过查看这个,我还发现有人在 magento Q&A of stack exchange his module to have a more secure password encryption 上发帖。
它在 GitHub 上采用 BSD 许可,因此 here is his post on the network
here is the module, called pbkdf2, repository

也许您可以从他的实现方式中找到一些有用的东西(我没有花时间看他的代码,太难了)。

Mage_Core_Model_Encryption 的 encrypt/decrypt 函数未在 url 中使用。

基本上,有两种方法可以解决冲突。一种是基于在客户身份验证方法上使用事件观察器来实现新的哈希。另一种方法,对我来说效果更好的方法是扩展 Mage_Adminhtml_Model_Url 并覆盖 getSecretKey 方法。 [评论中链接的两个回购协议对我们的学习很有帮助。]

为了解决这个问题,我在 models:

的 config.xml 中添加了一个节点
<adminhtml>
  <rewrite>
    <url>Mycompany_Encryption_Model_Adminhtml_Url</url>
  </rewrite>
</adminhtml>

然后添加文件Mycompany/Encryption/Model/Adminhtml/Url.php:

class Mycompany_Encryption_Model_Adminhtml_Url extends Mage_Adminhtml_Model_Url
{
    public function getSecretKey($controller = null, $action = null)
    {
        $salt = Mage::getSingleton('core/session')->getFormKey();
        $p = explode('/', trim($this->getRequest()->getOriginalPathInfo(), '/'));

        if (!$controller) {
            $controller = !empty($p[1]) ? $p[1] : $this->getRequest()->getControllerName();
        }

        if (!$action) {
             $action = !empty($p[2]) ? $p[2] : $this->getRequest()->getActionName();
        }
        $secret = $controller . $action . $salt;

        // Overriding getHash() to use a diff hash than passwords.
         return Mage::helper('core')->getEncryptor()->urlHash($secret);
    }
}

最后,我通过添加 urlHash 方法更新了我的 Mycompany/Encryption/Model/Encryption.php(除了已经位于那里的 hashvalidateHashgetHash 函数):

public function urlHash($value)
{
    return md5($value);
}

我本可以在 getSecretKey 的末尾返回 md5($secret),这也有效,但此方法演示了更多有助于实际操作的 Mage 方法。

我还没有完全测试我的模块,但这似乎与调用 getSecretKey 的每个地方都完全兼容。