2011-12-04 15 views
6

Sto usando Symfony 2 con Doctrine 2.Dove criptare/decodificare i miei dati?

Ho bisogno di crittografare un campo nella mia entità utilizzando un servizio di crittografia, e mi chiedo dove dovrei mettere questa logica.

Utilizzo un controller> Servizio> Architettura repository.

Mi chiedevo se un ascoltatore sarebbe una buona idea, la mia preoccupazione principale è, se la mia entità è archiviata crittografata, se la decifro al volo il suo stato sarà cambiato e non sono sicuro che sia una buona idea.

Come implementeresti questo?

risposta

14

Non so se è il modo giusto, ma l'ho implementato di recente creando un custom mapping type, come per i documenti Doctrine. Qualcosa di simile a quanto segue:

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; 
    } 
} 

ho registrato questo tipo nella mia classe bundle:

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 :-) 
     } 
    } 
} 

e poi sono stato in grado di fare riferimento a quando la creazione i miei soggetti, ad esempio:

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

Questa è stata un'implementazione rapida, quindi sarei interessato a conoscere il modo corretto di farlo. Presumo anche che il tuo servizio di crittografia sia qualcosa disponibile dal container; Non so come possibile/possibile sarebbe quello di passare servizi in tipi personalizzati in questo modo sia ... :-)

+0

ciao, grazie tua risposta, è sicuramente una buona idea, ma mi chiedo come ho potuto passare la mia chiave privata? Diciamo che passo il mio EncryptionService al mio tipo personalizzato usando il costruttore, ho ancora bisogno di passarlo una chiave da usare per la crittografia, tuttavia, poiché il tipo viene usato quando si persiste e si idrata un'entità, non so come potrei fai questo – Trent

+0

Sì, nel nostro caso abbiamo usato le funzioni 'mcrypt_ *' e abbiamo codificato l'iv e la passphrase ecc. a causa di limiti di tempo, ma non so se potresti, ad esempio, creare il tipo come servizio e passare i parametri in quel modo . Sembra essere una mancanza di informazioni su come farlo in modo efficiente! – richsage

+0

Sì, sto effettivamente utilizzando le funzioni mcrypt_ *, ma la chiave per crittografare i dati viene generata dinamicamente, quindi non posso hardcode. – Trent

8

la risposta di Richsage era piuttosto buona, tranne che non vorrei registrare il tipo personalizzato nel pacchetto di file di classe. Si consiglia di utilizzare il config.yml in questo modo:

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

Poi basta assicurarsi che nella tua classe EncryptedStringType si specifica la funzione getName di tornare encrypted_string.

Ora nella definizione del modello (o annotazione) è possibile utilizzare il tipo encrypted_string.

+0

bello, è molto più pulito :-) – richsage

17

Per espandere il richsage e s' targnation grandi risposte, in un modo per iniettare una dipendenza (ad esempio, il servizio cypto) in un tipo di mappatura Doctrine personalizzato, potrebbe essere quella di utilizzare una proprietà statica e 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'; 
    } 
} 

configurazione sarebbe simile a questa:

// 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% ] 
Problemi correlati