在哪里加密/解密我的数据?

Tre*_*ent 6 encryption symfony doctrine-orm

我正在使用Symfony 2和Doctrine 2.

我需要使用加密服务加密我的实体中的字段,我想知道我应该把这个逻辑放在哪里.

我正在使用Controller> Service> Repository体系结构.

我想知道一个听众是不是一个好主意,我主要担心的是,如果我的实体是加密存储的,如果我在飞行中解密它的状态它会被改变,我不确定这是个好主意.

你会如何实现这个?

Cy *_*y K 17

为了扩展richsagetargnation的好答案,将依赖项(例如,cypto服务)注入自定义Doctrine映射类型的一种方法是使用静态属性和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';
    }
}
Run Code Online (Sandbox Code Playgroud)

配置看起来像这样:

// 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% ]
Run Code Online (Sandbox Code Playgroud)


ric*_*age 14

我不知道它是否是正确的方法,但我最近通过创建自定义映射类型实现了这一点,根据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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我在我的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 :-)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我在创建实体时能够引用它,例如:

/**
 * @ORM\Column(type="encryptedstring")
 * @Assert\NotBlank()
 */
protected $name;
Run Code Online (Sandbox Code Playgroud)

这是一个快速实现,所以我有兴趣知道这样做的正确方法.我还假设您的加密服务可以从容器中获得; 我不知道以这种方式将服务传递到自定义类型是否可行/可能...... :-)

  • FWIW静态IV(在所有加密中共享)可以解决许多问题:http://security.stackexchange.com/questions/1093/forced-into-using-a-static-iv-aes (2认同)

tar*_*ion 8

richsage的答案非常好,除了我不会在bundle类文件中注册自定义类型.建议你像这样使用config.yml:

# ./app/config/confi
doctrine:
    dbal:
        driver:   "%database_driver%"
        {{ etc, etc }}
        types:
            encrypted_string: MyCompany\MyBundle\Type\EncryptedStringType
Run Code Online (Sandbox Code Playgroud)

然后确保在EncryptedStringType类中指定getName函数以返回encrypted_string.

现在,在模型定义(或注释)中,您可以使用encrypted_string类型.