問(wèn)題描述
我想在添加/編輯時(shí)加密一些表單字段,并在蛋糕查找它們時(shí)對(duì)其進(jìn)行解密.這是在 v2.7.2 中對(duì)我有用的代碼:
I want to have some form-fields encrypted when they are added/edited and decrypted when they are looked up by cake. Here is the code that works for me in v2.7.2:
core.php
Configure::write('Security.key','secretkey');
app/model/patient.php.
app/model/patient.php.
public $encryptedFields = array('patient_surname', 'patient_first_name');
public function beforeSave($options = array()) {
foreach($this->encryptedFields as $fieldName){
if(!empty($this->data[$this->alias][$fieldName])){
$this->data[$this->alias][$fieldName] = Security::encrypt(
$this->data[$this->alias][$fieldName],
Configure::read('Security.key')
);
}
}
return true;
}
public function afterFind($results, $primary = false) {
foreach ($results as $key => $val) {
foreach($this->encryptedFields as $fieldName) {
if (@is_array($results[$key][$this->alias])) {
$results[$key][$this->alias][$fieldName] = Security::decrypt(
$results[$key][$this->alias][$fieldName],
Configure::read('Security.key')
);
}
}
}
return $results;
}
據(jù)我所知,我必須將 $this->data[] 替換為模型生成的實(shí)體,并將 afterFind 方法替換為虛擬字段,但我無(wú)法將它們放在一起.
As I understand it I have to replace $this->data[] with the generated entities for the model and the afterFind method with virtual fields, but I just can't put it all together.
推薦答案
解決這個(gè)問(wèn)題的方法不止一種(請(qǐng)注意以下代碼是未經(jīng)測(cè)試的示例代碼!在使用任何新的基礎(chǔ)知識(shí)之前,您應(yīng)該先掌握新的基礎(chǔ)知識(shí))這個(gè)).
There's more than one way to solve this (please note that the following code is untested example code! You should get a grasp on the new basics first before using any of this).
一種是自定義數(shù)據(jù)庫(kù)類(lèi)型,它會(huì)在將值綁定到數(shù)據(jù)庫(kù)語(yǔ)句時(shí)進(jìn)行加密,并在獲取結(jié)果時(shí)進(jìn)行解密.這是我更喜歡的選項(xiàng).
One would be a custom database type, which would encrypt when binding the values to the database statement, and decrypt when results are being fetched. That's the option that I would prefer.
這是一個(gè)簡(jiǎn)單的例子,假設(shè) db 列可以保存二進(jìn)制數(shù)據(jù).
Here's simple example, assuming the db columns can hold binary data.
src/Database/Type/CryptedType.php
這應(yīng)該是不言自明的,轉(zhuǎn)換到數(shù)據(jù)庫(kù)時(shí)加密,轉(zhuǎn)換到 PHP 時(shí)解密.
This should be rather self explantory, encrypt when casting to database, decrypt when casting to PHP.
<?php
namespace AppDatabaseType;
use CakeDatabaseDriver;
use CakeDatabaseType;
use CakeUtilitySecurity;
class CryptedType extends Type
{
public function toDatabase($value, Driver $driver)
{
return Security::encrypt($value, Security::getSalt());
}
public function toPHP($value, Driver $driver)
{
if ($value === null) {
return null;
}
return Security::decrypt($value, Security::getSalt());
}
}
src/config/bootstrap.php
注冊(cè)自定義類(lèi)型.
use CakeDatabaseType;
Type::map('crypted', 'AppDatabaseTypeCryptedType');
src/Model/Table/PatientsTable.php
最后將可加密列映射到注冊(cè)類(lèi)型,就是這樣,從現(xiàn)在開(kāi)始,一切都會(huì)自動(dòng)處理.
Finally map the cryptable columns to the registered type, and that's it, from now on everything's being handled automatically.
// ...
use CakeDatabaseSchemaTable as Schema;
class PatientsTable extends Table
{
// ...
protected function _initializeSchema(Schema $table)
{
$table->setColumnType('patient_surname', 'crypted');
$table->setColumnType('patient_first_name', 'crypted');
return $table;
}
// ...
}
參見(jiàn)食譜>數(shù)據(jù)庫(kù)訪問(wèn)ORM >數(shù)據(jù)庫(kù)基礎(chǔ)添加自定義類(lèi)型
See Cookbook > Database Access & ORM > Database Basics > Adding Custom Types
一種不那么枯燥和緊密耦合的方法,基本上是您 2.x 代碼的一個(gè)端口,將使用 beforeSave
回調(diào)/事件和結(jié)果格式化程序.例如,結(jié)果格式化程序可以附加在 beforeFind
事件/回調(diào)中.
A less dry and tighter coupled approach, and basically a port of your 2.x code, would be to use the beforeSave
callback/event, and a result formatter. The result formatter could for example be attached in the beforeFind
event/callback.
在 beforeSave
中只需設(shè)置/獲取傳入實(shí)體實(shí)例的值,您可以使用 Entity::has()
, Entity::get()
和 Entity::set()
,甚至使用數(shù)組訪問(wèn),因?yàn)閷?shí)體實(shí)現(xiàn)了 ArrayAccess
.
In beforeSave
just set/get the values to/from the passed entity instance, you can utilize Entity::has()
, Entity::get()
and Entity::set()
, or even use array access since entities implement ArrayAccess
.
結(jié)果格式化程序基本上是一個(gè) after find 鉤子,您可以使用它輕松地迭代結(jié)果并修改它們.
The result formatter is basically an after find hook, and you can use it to easily iterate over results, and modify them.
這是一個(gè)基本的例子,不需要太多解釋:
Here's a basic example, which shouldn't need much further explanation:
// ...
use CakeEventEvent;
use CakeORMQuery;
class PatientsTable extends Table
{
// ...
public $encryptedFields = [
'patient_surname',
'patient_first_name'
];
public function beforeSave(Event $event, Entity $entity, ArrayObject $options)
{
foreach($this->encryptedFields as $fieldName) {
if($entity->has($fieldName)) {
$entity->set(
$fieldName,
Security::encrypt($entity->get($fieldName), Security::getSalt())
);
}
}
return true;
}
public function beforeFind(Event $event, Query $query, ArrayObject $options, boolean $primary)
{
$query->formatResults(
function ($results) {
/* @var $results CakeDatasourceResultSetInterface|CakeCollectionCollectionInterface */
return $results->map(function ($row) {
/* @var $row array|CakeDataSourceEntityInterface */
foreach($this->encryptedFields as $fieldName) {
if(isset($row[$fieldName])) {
$row[$fieldName] = Security::decrypt($row[$fieldName], Security::getSalt());
}
}
return $row;
});
}
);
}
// ...
}
為了稍微解耦,您還可以將其移動(dòng)到行為中,以便您可以輕松地在多個(gè)模型之間共享它.
To decouple this a little, you could also move this into a behavior so that you can easily share it across multiple models.
另見(jiàn)
- 食譜>數(shù)據(jù)庫(kù)訪問(wèn)ORM >數(shù)據(jù)庫(kù)基礎(chǔ)添加自定義類(lèi)型
- 食譜>數(shù)據(jù)庫(kù)訪問(wèn)ORM >查詢(xún)生成器添加計(jì)算字段
- 食譜>教程 &例子 >書(shū)簽教程第 2 部分 >保留標(biāo)簽字符串
- 食譜>數(shù)據(jù)庫(kù)訪問(wèn)ORM >行為
- API >CakeDatasourceEntityTrait
- API >CakeORMTable
這篇關(guān)于CakePHP 3 中表單字段的加密/解密的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!