2011-12-04 77 views
6

我使用Symfony 2與Doctrine 2.在哪裏加密/解密我的數據?

我需要使用加密服務加密我的實體中的字段,我想知道我應該在哪裏放置這個邏輯。

我正在使用控制器>服務>存儲庫架構。

我想知道如果一個聽衆是一個好主意,我的主要擔心是,如果我的實體存儲加密,如果我在飛行中解密它的狀態它將會改變,我不知道這是一個好理念。

你將如何實現這一點?

回答

14

我不知道它是否是正確的方法,但我最近通過創建custom mapping type來實現這一點,按照Doctrine文檔。像下面這樣:

class EncryptedStringType extends TextType 
{ 
    const MYTYPE = 'encryptedstring'; // modify to match your type name 

    public function convertToPHPValue($value, AbstractPlatform $platform) 
    { 
     return base64_decode($value); 
    } 

    public function convertToDatabaseValue($value, AbstractPlatform $platform) 
    { 
     return base64_encode($value); 
    } 

    public function getName() 
    { 
     return self::MYTYPE; 
    } 
} 

我註冊這個類型在我的包類:

class MyOwnBundle extends Bundle 
{ 
    public function boot() 
    { 
     $em = $this->container->get("doctrine.orm.entity_manager"); 
     try 
     { 
      Type::addType("encryptedstring", "My\OwnBundle\Type\EncryptedStringType"); 

      $em-> 
       getConnection()-> 
       getDatabasePlatform()-> 
       registerDoctrineTypeMapping("encryptedstring", "encryptedstring"); 
     } catch (\Doctrine\DBAL\DBALException $e) 
     { 
      // For some reason this exception gets thrown during 
      // the clearing of the cache. I didn't have time to 
      // find out why :-) 
     } 
    } 
} 

,然後我就能夠創建我的實體,例如當參考吧:

/** 
* @ORM\Column(type="encryptedstring") 
* @Assert\NotBlank() 
*/ 
protected $name; 

這是一個快速實施,所以我很想知道正確的做法。我還假定你的加密服務是容器中可用的東西;我不知道這將是多麼可行/可服務傳遞到這樣無論是自定義類型... :-)

+0

您好,感謝您的回答,這絕對是一個好主意,但是我不知道我怎麼會通過我的私鑰? 假設我使用構造函數將EncryptionService傳遞給了我的Custom類型,但我仍然需要將它傳遞給一個用於加密的密鑰,但是,因爲在持久化和保溼實體時使用了類型,所以我不知道如何才能這樣做 – Trent

+0

是的,在我們的例子中,我們使用了'mcrypt_ *'函數,並且由於時間限制而對iv和passphrase等進行了硬編碼,但是我不知道您是否可以將類型創建爲服務並以這種方式傳遞參數。似乎缺乏有關如何有效地做到這一點的信息! – richsage

+0

是的,我實際上使用mcrypt_ *函數,但加密數據的密鑰是動態生成的,因此我無法對其進行硬編碼。 – Trent

8

richsage的答案是相當不錯的,但我不會在註冊自定義類型捆綁類文件。我們建議您使用config.yml像這樣:

# ./app/config/confi 
doctrine: 
    dbal: 
     driver: "%database_driver%" 
     {{ etc, etc }} 
     types: 
      encrypted_string: MyCompany\MyBundle\Type\EncryptedStringType 

然後只需確保在你的EncryptedStringType類,你指定的getName函數返回encrypted_string。

現在在您的模型定義(或註釋)中,您可以使用encrypted_string類型。

+0

不錯,這是更清潔:-) – richsage

17

要擴大richsagetargnation的偉大的答案,注入的依賴的一種方式(例如,cypto服務)到自定義學說映射類型,可以使用一個靜態屬性和setter:

// MyBundle/Util/Crypto/Types/EncryptedString.php 
class EncryptedString extends StringType 
{ 
    /** @var \MyBundle\Util\Crypto */ 
    protected static $crypto; 

    public static function setCrypto(Crypto $crypto) 
    { 
     static::$crypto = $crypto; 
    } 

    public function convertToDatabaseValue($value, AbstractPlatform $platform) 
    { 
     $value = parent::convertToDatabaseValue($value, $platform); 
     return static::$crypto->encrypt($value); 
    } 

    public function convertToPHPValue($value, AbstractPlatform $platform) 
    { 
     $value = parent::convertToPHPValue($value, $platform); 
     return static::$crypto->decrypt($value); 
    } 

    public function getName() 
    { 
     return 'encrypted_string'; 
    } 
} 

配置是這樣的:

// MyBundle/MyBundle.php 
class MyBundle extends Bundle 
{ 
    public function boot() 
    { 
     /** @var \MyBundle\Util\Crypto $crypto */ 
     $crypto = $this->container->get('mybundle.util.crypto'); 
     EncryptedString::setCrypto($crypto); 
    } 
} 

# app/Resources/config.yml 
doctrine: 
    dbal: 
     types: 
      encrypted_string: MyBundle\Util\Crypto\Types\EncryptedString 

# MyBundle/Resources/config/services.yml 
services: 
    mybundle.util.crypto: 
     class: MyBundle\Util\Crypto 
     arguments: [ %key% ]