所以我的数据库中有一个实体中的字段
class Person
{
// other fields
/**
* @var string
*
* @ORM\Column(name="last_name", type="string", length=50, nullable=false)
*/
private $lastName;
/**
* @var string
*
* @ORM\Column(name="first_name", type="string", length=50, nullable=false)
*/
private $firstName;
// getters and setters
}我有一个叫SecureEncryptor的服务。它具有解密()和Encrypt()函数--基本上,您只需将加密/未加密(分别)的字符串传递给它,它就会执行以下操作。
问题是,我不知道如何与实体一起使用该服务--特别是在考虑表单(类型)时。我的意思是,我知道我只需要得到字段并调用Decrypt函数,但是对于绑定到Person实体的Type,这是行不通的。
我开始为被解密的人创建一个单独的实体,然后我会在处理数据库的时候切换它,但这似乎是错误的。我的另一个想法是从实体中调用服务,但我也读到这是错误的。
有什么想法吗?
编辑:
这基本上就是我想要做的:
$builder->get('dateOfBirth')
->addModelTransformer(new CallbackTransformer(
function ($encryptedDOB) {
return $this->encryptor->decrypt($encryptedDOB, salt); // How do I get the salt value here?
},
function ($decryptedDOB) {
return $this->encryptor->encrypt($decryptedDOB, salt); // How do I get the salt value here?
}
));或者在这一步之前对数据进行解密/加密,但不确定如何实现。
编辑2:
我找到了这,它显示您可以在PRE_SET_DATA事件中访问实体数据,但是您不能在其中添加一个数据转换器,所以不确定它如何工作。
发布于 2018-10-05 07:07:47
在经历了三天的混乱--可能是20+几个小时的挫折--之后,我终于找到了正确的方法。实体事件侦听器
所以我做了以下修改
app\config\services.yaml
parameters:
...
encryption_key: '%kernel.project_dir%/path/to/my/key'
services:
...
App\EventListeners\PatientListener:
arguments: [@session]
tags:
- { name: doctrine.event_listener, event: prePersist }
- { name: doctrine.event_listener, event: preUpdate }
- { name: doctrine.event_listener, event: postLoad }然后我做了服务
<?php
namespace App\EventListeners;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use App\Entity\Patients;
use ParagonIE\Halite\HiddenString;
use ParagonIE\Halite\KeyFactory;
use ParagonIE\Halite\Symmetric\Crypto as Symmetric;
use ParagonIE\Halite\Symmetric\EncryptionKey;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\Session\Session;
class PatientListener
{
private $params;
private $session;
private $logger;
public function __construct(ParameterBagInterface $params,
Session $session, LoggerInterface $logger)
{
$this->params = $params;
$this->session = $session;
$this->logger = $logger;
}
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getObject();
if ($entity instanceof Patients)
{
$this->encryptFields($entity);
}
}
public function preUpdate(LifecycleEventArgs $args)
{
$entity = $args->getObject();
if ($entity instanceof Patients)
{
$this->encryptFields($entity);
}
}
public function postLoad(LifecycleEventArgs $args)
{
$entity = $args->getObject();
if ($entity instanceof Patients)
{
$this->decryptFields($entity);
}
}
private function loadKey() : EncryptionKey
{
try
{
KeyFactory::loadEncryptionKey($this->params->get('encryption_key'));
}
catch(\Throwable $e)
{
$this->session->getFlashBag()->add('danger', 'Unable to load encryption key!');
$this->logger->emergency(
'Unable to lod the encryption key!', array(
'error' => $e->getMessage(),
));
throw;
}
}
private function encryptFields(Patients $patient)
{
$key = $this->loadKey();
// Encrypt the variables
$lastName = $this->encrypt('Last Name', $patient->getLastName(), $key);
// Set the entity variables
$patient->setLastName($lastName);
return $patient;
}
private function encrypt($fieldName, $value, $key)
{
try {
return Symmetric::encrypt(
new HiddenString($value),
$key
);
} catch(\Throwable $e)
{
$this->session->getFlashBag()->add('danger', 'Unable to encrypt field');
$this->logger->critical(
'Unable to encrypt field "'.$fieldName.'" in Patients entity. DB update terminated.', array(
'error' => $e->getMessage(),
));
throw;
}
}
private function decryptFields(Patients $patient)
{
$key = $this->loadKey();
$id = $patient->getId();
// Decrypt the variables
$lastName = $this->decrypt($id, 'Last Name', $patient->getLastName(), $key);
// Set the entity variables
$patient->setLastName($lastName);
}
private function decrypt($id, $fieldName, $value, $key)
{
try
{
return Symmetric::decrypt($value, $key);
}
catch (\Throwable $e)
{
$this->session->getFlashBag()->add('warning', 'Unable to decrypt field');
$this->logger->warning(
'Unable to decrypt field "'.$fieldName.'" in Patients entity for ID: '.$id, array(
'error' => $e->getMessage(),
));
}
}
}现在,数据被加载到数据库时被加密,当数据加载到实体时被解密。
这种方法是正确的,因为这样做的任何其他方式(自定义原则类型,数据转换器,做它在控制器等)。如果其他人在另一个控制器中创建另一个表单或使用该实体,则总是有可能使数据解密(也就是非常糟糕)。这种方法确保数据始终通过理论被正确加密和解密(除非您做了一些定制的DQL\SQL,在这种情况下,您可能需要自己处理,这取决于您正在做什么)。
发布于 2018-10-03 06:09:13
如果我正确理解,您将寻找以透明方式在数据库中加载/存储加密数据的方法。我想我应该在加载/保存时在这里实现风俗主义类型和解密/加密。
编辑:不难实现,作为基础,您可以使用Doctrine\DBAL\Types\TextType,您将扩展,在那里您感兴趣的convertToPHPValue() -解密和convertToDatabaseValue()加密。更多的样本,看看和原则类型,定义,并找到一个最适合你的需要。
https://stackoverflow.com/questions/52617635
复制相似问题