2011-02-08 58 views
2

我有一個現有的非基於框架的PHP/MySQL網站。它有一個簡單的安全模型,帶有用戶名和散列(MD5)密碼的用戶表。將現有用戶和密碼遷移到新的Symfony/sfDoctrineGuard用戶系統

我目前正在研究本網站的「版本2」,這次使用Symfony和Doctrine。新版本工作正常,我使用sfDoctrineGuard插件進行用戶管理。

我想將現有用戶遷移到新的應用程序中,儘量不要大驚小怪,保留現有的用戶名和密碼。我的主要問題是,我想改變我使用的密碼哈希值。

當前站點使用無碼MD5哈希密碼*。我已經想出瞭如何在保持現有算法的同時將用戶遷移到Symfony/sfDoctrineGuard(通過爲未加化的MD5提供我自己的「算法」功能)。但是,未加化的md5顯然並不理想。

所以 - 我的問題是,由於我可以用我自定義的plain-MD5密碼散列算法成功遷移到sfDoctrineGuard用戶羣中,有什麼辦法可以轉換這些用戶,以便他們使用標準,醃製SHA1 sfDoctrineGuard算法?

我想我只能在每個用戶登錄時爲每個用戶執行此操作,因爲這是我唯一擁有用戶重新哈希密碼的明文密碼。我想我需要做的就是在「這個用戶剛剛用這個密碼成功登錄」的時候掛鉤了一些東西,這樣我就可以將用戶的算法,鹽和密碼設置到新的SHA1系統中,並將用戶保存回數據庫沒有他們甚至知道它。

我挖了一下,我找不到一種方法來覆蓋或掛鉤到sfDoctrineGuard(特別是sfGuardSecurityUser,我認爲?)登錄系統在正確的位置。那麼,不是沒有黑客入侵實際的插件文件,這似乎是邪惡的。

任何Symfony/sfDoctrineGuard專家都指出我在正確的方向嗎?

*不要看着我那樣,這是我的第一個網站!至少我沒有將它們存儲成明文...

回答

1

您有足夠的選項來解決您的問題。

您可以重載或更改sfDoctrineGuardPlugin中的幾乎所有內容。

如果您需要在sfGuardSecurityUser中更改某些內容,那麼您可以在應用程序的User類(它實際上擴展了sfGuardSecurityUser)中進行更改。

也可以重載默認放入lib/model/doctrine/sfDoctrineGuardPlugin目錄中的模型類。

您也可以擴展默認防護模式。例如,您可以添加一個字段,告訴您用戶是否更改了密碼,如果沒有,則更新密碼。

最後,您可以實現自定義密碼檢查和設置算法: http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin?tab=plugin_readme(滾動到「使用外部方法檢查用戶密碼」和「更改用於存儲密碼的算法」)。

+0

啊!這可能只是我需要的線索。我已經嘗試在我的myUser類中實現自己的checkPassword版本,但它從來沒有被調用(奇怪的是,它看起來像sfGuardSecurityUser的checkPassword()永遠不會被調用,這使它成爲一個紅鯡魚!)但進一步跟蹤事情,它實際上是進行檢查的PluginsfGuardUser,現在我知道在你提到的目錄中有一個可覆蓋的版本 - 我沒有發現 - 我應該能夠將我的代碼放在那裏。謝謝! – 2011-02-09 20:02:12

0

感謝庫巴,他指出我正確的方向。

爲了幫助其他任何想要做這種事的人,下面是我所做的。

首先,我將我現有的用戶(使用從舊數據庫轉儲的文本文件中的夾具加載)遷移到我的數據庫中。我使用了一種自定義算法,在數據加載過程中將未加密的MD5密碼保持不變(稱爲UniqueSentence :: unsaltednotransform)。這給了我sf_guard_user中的用戶在'algorithm'中'password'和'UniqueSentence :: unsaltednotransform'中的舊密碼散列值。 (你可以直接將行遷移到表中,我只是覺得把它作爲燈具很方便。)

然後,我在/lib/model/doctrine/sfDoctrineGuardPlugin/sfGuardUser.class中添加了自己的自定義checkPassword函數.PHP如下:

class sfGuardUser extends PluginsfGuardUser 
{ 
    public function checkPassword($password) 
    { 
    if ($this->getAlgorithm() == 'UniqueSentence::unsaltednotransform') { 
     // Our password has been set by a fixture load that left it in its 
     // original state from the old system, an unsalted MD5. 

     // Has the user got the right password? 
     if (md5($password) != $this->getPassword()) { 
     return false; 
     } 
     // Yes. So, now we re-set the password. 
     $this->setSalt(''); // An empty salt will be regenerated 
     // Use a smarter algorithm 
     $algorithm = sfConfig::get('app_sf_guard_plugin_algorithm_callable', 'sha1'); 
     $this->setAlgorithm($algorithm); 
     $this->setPassword($password); 
     // Could just return true here, but dropping through to the usual 
     // method means that if we've broken something, we'll know sooner 
     // rather than later. 
    } 
    // Just pass the call onto the usual method. 
    return parent::checkPasswordByGuard($password); 
    } 
} 

正如你所看到的,這是很簡單 - 如果它檢測到有老人的密碼算法,用戶,它驗證使用舊算法的密碼,然後,如果它的它會將算法更改爲SHA1,並重新設置密碼(首先設置鹽空白以便重新生成)。然後,它會直接使用基類中的標準checkPassword()。

這似乎工作成功 - 如果我作爲一個遷移的用戶登錄,它就像普通用戶一樣工作,但如果我以後檢查數據庫,他們的算法,salt和哈希密碼已按預期更新。

相關問題