如何在加密字段上使用 UniqueEntity 约束?
Posted
技术标签:
【中文标题】如何在加密字段上使用 UniqueEntity 约束?【英文标题】:How to use UniqueEntity constraint on an encrypted field? 【发布时间】:2022-01-19 14:08:11 【问题描述】:我正在开发一个基于 Symfony 4 的项目。我试图让 @UniqueEntity
在 @Encrypted
字段上工作,但我不知道如何操作。
@Encrypted
注释,@UniqueEntity
注释可以防止重复
使用@Encrypted
注释,@UniqueEntity
注释允许复制
/**
* @ORM\Entity(repositoryClass="App\Repository\DemoRepository")
* @ORM\HasLifecycleCallbacks()
* @UniqueEntity(
* fields="example",
* ignoreNull=true,
* )
*
*/
class Demo implements LoggableEntityInterface
/**
* @ORM\Column(type="text", nullable=true)
* @Encrypted
*/
private $example;
【问题讨论】:
在任何情况下,如果该字段实际上是加密的,Symfony 可能更难以检查是否没有任何其他具有相同值的字段。https://packagist.org/packages/michaeldegroot/doctrine-encrypt-bundle
是的,这是我的问题 :) 这是我找到的加密数据库中字段(如电子邮件等)的解决方案。如果您有任何建议,我可以尝试其他方法。
不知道那个包是如何工作的。但是拥有一个唯一的字段并对其进行加密并没有多大意义。如果您想在不破坏加密的情况下检查字段是否唯一,您可能希望将哈希存储在不同的字段中。
假设我正在添加一个新用户。我不想存储未加密的用户电子邮件,同时我想避免电子邮件重复。你会怎么做?
“我不想存储未加密的用户电子邮件”您介意在您的用例中提供一些上下文,其中电子邮件地址被视为如此您是否需要在 RDBMS 所做的任何静态加密的基础上对它们进行加密?我曾在一些非常敏感的环境中工作过,但我从未见过在将电子邮件地址插入任何类型的数据存储之前,在应用程序级别单独选择并对其进行加密。
【参考方案1】:
首先,我不知道 Encrypted
包是如何工作的,但如果字段的内容被加密,框架可能很难或不可能检查新值是否与旧值匹配。
这取决于字段的加密方式以及检查方式。 UniqueEntity
是一个验证检查,因此在保存值之前执行。它应该首先加密该值,并与加密值进行比较。 Symfony 注释不支持该工作流。
您可以存储字段的哈希值,设置Unique
检查哈希值,而不是字段。不过,它会为您的桌子增加相当多的存储空间。
一个简单的实现:
/**
* @ORM\Entity
* @UniqueEntity(
* fields="emailHash",
* ignoreNull=true,
* )
*
*/
class Foo
/**
* @ORM\Column(length="128")
* @Encrypted
*/
private $email;
/**
* @ORM\Column(length="40")
*/
private $emailHash;
public function getEmail(): string
return $this->email;
public function setEmail(string $email)
$this->email = $email;
$this->emailHash = hash('sha1', $email . get_class($this));
现在将对散列进行检查,散列不会被加密,但存储起来应该相对安全。请注意,我还使用类名作为“盐”,因此哈希稍微更安全。
或者,您可以使用注释的repositoryMethod
键,并创建一个自定义存储库方法,该方法采用原始值,对其进行加密,并通过加密值执行搜索。这意味着您了解如何使用您的加密包正在使用的任何工具,因此您可以在新的存储库方法中使用它。
【讨论】:
感谢您的回答!我会玩一会儿,然后回复你:)以上是关于如何在加密字段上使用 UniqueEntity 约束?的主要内容,如果未能解决你的问题,请参考以下文章
Symfony UniqueEntity vs UniqueConstraint vs unique=true