Как использовать метод sql «AES_DECRYPT» в afterFind в YII2

Мне нужно использовать метод sql AES_DECRYPT, но строка не расшифровывается.

он работает в sql, но не в методе afterfind yii2

он возвращает ответ, как показано ниже. введите здесь описание изображения

Это ниже изображения таблицы БД. введите здесь описание изображения

 public function afterFind() {
            parent::afterFind();

            //$this->name = new Expression('AES_DECRYPT("'.$this->name.'", "key test")  as name ');
            $this->name = new Expression('cast(AES_DECRYPT("'.$this->encrypt_name.'", "key test") as char) as name');

            //return true;

        }

person Bhavin Thummar    schedule 04.04.2018    source источник
comment
AES_DECRYPT не будет работать в afterFind(), поскольку он должен быть обработан MySql (вы можете использовать PHP, но тогда вы, скорее всего, также захотите зашифровать его в PHP). Можно ли использовать выражение AES_DECRYPT при извлечении данных путем изменения запроса select или аналогичного?   -  person ldg    schedule 04.04.2018
comment
deos, это поможет вам stackoverflow.com/questions/16556375/   -  person Muhammad Omer Aslam    schedule 04.04.2018
comment
Нет, сэр, мне это не поможет.   -  person Bhavin Thummar    schedule 05.04.2018
comment
какая именно ошибка? какой именно запрос был сформирован? просто взгляните на выполненный запрос. Вы можете найти выполненный запрос на панели инструментов отладки.   -  person R13e    schedule 05.04.2018
comment
@ R13e Пожалуйста, посмотрите скриншот таблицы БД. Мне понадобится точный запрос в скриншоте таблицы БД. Как я поместил AES_DECRYPT в метод afterfind.   -  person Bhavin Thummar    schedule 05.04.2018
comment
Я думаю, вы неправильно поняли мои вопросы и концепцию afterFind. Вы хотите расшифровать во время запроса или после? Если вы вызываете afterFind() в модели, вы делаете это после выполнения запроса. Таким образом, использование класса, такого как yii\db\Expression, для какого-либо уже заполненного атрибута не имеет смысла.   -  person R13e    schedule 05.04.2018


Ответы (2)


Я надеюсь, что это полезно для вас:

    public function afterFind() {
        $this->name = (new Query)->select(['AES_DECRYPT("'.$this->encrypt_name.'", "key test") as name'])->scalar();
        return true;
    }
person Harsh Panchal    schedule 05.04.2018
comment
Спасибо, сэр, за вашу большую помощь. - person Bhavin Thummar; 05.04.2018
comment
Это создаст дополнительный запрос для каждой модели (отображение 50 моделей на одной странице даст вам 50 дополнительных запросов). Взгляните на мой ответ, который должен сделать всю магию в одном запросе. - person rob006; 07.04.2018
comment
Также вы должны вызывать parent::afterFind() вместо return true. - person rob006; 07.04.2018

afterFind() вызывается после выполнения SQL-запроса, слишком поздно изменять запрос и использовать SQL-выражения. Вы должны изменить select полей, прежде чем вызывать one() или all().

return MyModel::find()
    ->addSelect(['cast(AES_DECRYPT(encrypt_name, "key test") as char) as name'])
    ->one();

Вы можете переопределить метод find() в своей модели, чтобы делать это автоматически для каждого запроса:

public static function find() {
    return parent::find()
        ->addSelect(['cast(AES_DECRYPT(encrypt_name, "key test") as char) as name']);
}

Вы можете передумать вообще не использовать AES_DECRYPT. Когда дело доходит до шифрования, по соображениям безопасности лучше шифровать как можно раньше, а расшифровывать как можно позже. Перемещение шифрования на уровне SQL создает несколько угроз:

  • Ваш SQL-запрос может быть зарегистрирован (в журнале ошибок или медленных запросов) или отображаться в сообщении об исключении. Это раскроет ваш ключ шифрования, что сделает все шифрование совершенно бессмысленным.
  • Поскольку вы отправляете ключ шифрования и незашифрованные данные между PHP и сервером MySQL, злоумышленник может получить к ним доступ, используя MITM-атака.
  • Компрометация SQL-сервера даст злоумышленнику доступ к зашифрованным данным, поскольку вы довольно часто отправляете ключ шифрования в SQL-запросе.

Вы можете избежать этого, шифруя и расшифровывая данные на уровне PHP (используя безопасность Yii компонент или некоторая библиотека). Вы можете сделать это прозрачным, создав виртуальный атрибут с помощью сеттера и геттера:

public function getName() {
    return $this->decrypt($this->encrypted_name);
}

public function setName($value) {
    $this->encrypted_name = $this->encrypt($value);
}

Затем вы можете получить доступ к незашифрованным данным с помощью $model->name.

person rob006    schedule 07.04.2018
comment
Спасибо, сэр, ваш ответ тоже правильный, но мне уже ответил другой человек. - person Bhavin Thummar; 09.04.2018