我正在使用Symfony 2和Doctrine 2.
我需要使用加密服务加密我的实体中的字段,我想知道我应该把这个逻辑放在哪里。
我正在使用控制器>服务>存储库架构。
我想知道听众是不是一个好主意,我主要担心的是,如果我的实体是加密存储的,如果我在飞行中解密它的状态它会被改变,我不确定这是个好主意
你会如何实现这个?
答案 0 :(得分:17)
扩展 richsage 和 targnation 的好答案,将依赖关系(例如,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';
}
}
配置如下所示:
// 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% ]
答案 1 :(得分: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;
这是一个快速实现,所以我有兴趣知道这样做的正确方法。我还假设您的加密服务可以从容器中获得;我不知道以这种方式将服务传递到自定义类型是多么可行/可能......: - )
答案 2 :(得分:8)
richsage的答案非常好,除了我不会在bundle类文件中注册自定义类型。建议你像这样使用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类型。