2011-12-04 34 views
6

Estoy usando Symfony 2 con Doctrine 2.¿Dónde cifrar/descifrar mis datos?

Necesito encriptar un campo en mi entidad utilizando un servicio de cifrado, y me pregunto dónde debería poner esta lógica.

Estoy usando una arquitectura de Controlador> Servicio> Repositorio.

Me preguntaba si un oyente sería una buena idea, mi principal preocupación es, si mi entidad está almacenada encriptada, si la descifro sobre la marcha, su estado cambiará y no estoy seguro de que sea una buena idea. idea.

¿Cómo implementarías esto?

Respuesta

14

No sé si es la manera correcta en absoluto, pero lo implementé recientemente creando un custom mapping type, según los documentos de Doctrine. Algo así como lo siguiente:

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

Me he registrado este tipo en mi clase de paquete:

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

y entonces yo era capaz de hacer referencia al crear mis entidades, por ejemplo:

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

Esta fue una implementación rápida, por lo que me interesaría saber la forma correcta de hacerlo. También supongo que su servicio de cifrado es algo disponible desde el contenedor; No sé qué tan factible/posible sería pasar servicios a tipos personalizados de esta manera tampoco ... :-)

+0

hola, gracias a su respuesta, sin duda es una buena idea, sin embargo me pregunto cómo pude pasar mi clave privada? Digamos que paso mi EncryptionService a mi tipo personalizado usando el constructor, aún necesito pasarle una clave para usar para el cifrado, sin embargo, como el tipo se usa para persistir e hidratar una entidad, no sé cómo podría hacer eso – Trent

+0

Sí, en nuestro caso usamos las funciones 'mcrypt_ *' y codificamos la iv y la frase de contraseña, etc., debido a limitaciones de tiempo, pero no sé si podrías crear el tipo como un servicio y pasar los parámetros de esa manera . ¡Parece ser una falta de información sobre cómo hacer esto de manera eficiente! – richsage

+0

Sí, en realidad estoy usando las funciones mcrypt_ *, pero la clave para encriptar datos se genera dinámicamente, así que no puedo codificarla. – Trent

8

de richsage la respuesta fue bastante buena, excepto que no registraría el tipo personalizado en el archivo de clase de paquete. Se recomienda que utilice el config.yml así:

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

A continuación, sólo asegúrese de que en la clase EncryptedStringType se especifica la función getNombre para volver encrypted_string.

Ahora, en la definición (o anotación) de su modelo, puede utilizar el tipo de cadena cifrada.

+0

bueno, eso es mucho más limpio :-) – richsage

17

Para ampliar richsage y targnation 's grandes respuestas, una manera de inyectar una dependencia (por ejemplo, el servicio cypto) en un tipo de asignación Doctrina costumbre, podría ser el uso de una propiedad estática y 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'; 
    } 
} 

configuración se vería así:

// 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% ] 
Cuestiones relacionadas