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.