Laravel Eloquent - Шифрование/Расшифровка данных по вызову
Я могу использовать Crypt
для шифрования/дешифрования моих данных. Я хочу зашифровать некоторую информацию в моем db (например, имя, адрес электронной почты, номер телефона, чтобы назвать несколько).
Предполагая, что я хочу, чтобы все было зашифровано, я хочу иметь возможность сделать это в фоновом режиме сам по себе, что я могу выполнить, перезаписав функции create
и save
:
// For instance, the save() function could become
public function save(array $options = array())
{
foreach ($this->attributes as $key => $value)
{
if (isset($value)) $this->attributes[$key] = Crypt::encrypt($value);
}
return parent::save($options);
}
Теперь я хочу, чтобы дешифрование выполнялось таким же образом, так что, когда я говорю User::find($id)
, возвращаемый $user
уже расшифрован. Также существуют другие функции, такие как firstOrFail()
get()
first()
, и все они также работают.
Мне также хотелось бы расширить эту функциональность, когда я использую отношения (так что User::with('someOtherTable')->find($id)
также работает).
Возможно ли это? Если это невозможно, я думаю о создании вспомогательной функции decyrpt()
function decrypt($array)
{
if (!is_array($array)) return Crypt::decrypt($array);
$result = [];
foreach($array as $key => $value) $result[$key] = decrypt($value);
return $result;
}
И передайте все мои результаты с помощью этого первого, а затем начните использовать их, но было бы лучше, если бы Laravel предоставил это, или если был "Laravel Way" этого.
Ответы
Ответ 1
На самом деле нет смысла шифровать все. Например, вы никогда не хотите шифровать первичный ключ; это даже не имеет смысла. Аналогично, вы, вероятно, не хотите шифровать поля даты; вы потеряете возможность выполнять какой-либо SQL-запрос на них.
С учетом этого вы можете попробовать что-то вроде этого:
class BaseModel extends Eloquent {
protected $encrypt = [];
public function setAttribute($key, $value)
{
if (in_array($key, $this->encrypt))
{
$value = Crypt::encrypt($value);
}
return parent::setAttribute($key, $value);
}
public function getAttribute($key)
{
if (in_array($key, $this->encrypt))
{
return Crypt::decrypt($this->attributes[$key]);
}
return parent::getAttribute($key);
}
public function attributesToArray()
{
$attributes = parent::attributesToArray();
foreach ($attributes as $key => $value)
{
if (in_array($key, $this->encrypt))
{
$attributes[$key] = Crypt::decrypt($value);
}
}
return $attributes;
}
}
тогда у вас все модели будут расширять этот вариант и устанавливают свойство $encrypt
для любых колонок, которые вы хотите зашифровать для этой конкретной модели.
P.S. Если вы хотите использовать функцию доступа Eloquent, вам придется немного поиграть с ней.
Ответ 2
Стоит отметить библиотеку Elocrypt для Laravel 4. Это более сложное решение, которое работает одинаково. Если вы используете Laravel 5, используйте вместо этого: Elocrypt 5.