Храните конфиденциальные данные в Silverstripe 3.1

Я хочу хранить конфиденциальную информацию (в основном пароли) в объекте данных в silverstripe. Данные должны храниться в зашифрованном виде в базе данных. Если я вызову это поле в своем шаблоне, мне нужно расшифровать данные.

Но я не знаю, как это сделать. Может ли кто-нибудь указать мне в правильном направлении?

Спасибо!


person invictus    schedule 29.09.2013    source источник
comment
хранение данных пароля с помощью обратимого хэша немного противоречит идее безопасности? Решением может быть использование ключа шифрования, но если этот ключ скомпрометирован, все ваши данные будут скомпрометированы, особенно потому, что этот ключ должен быть доступен серверу в любое время, поэтому он подвергается риску....   -  person colymba    schedule 29.09.2013
comment
Почему вы хотите вызвать это в своем шаблоне? Вы хотите показать пароль пользователю? Или просто проверить, правильно ли введен пароль?   -  person 3dgoo    schedule 30.09.2013
comment
я хочу показать его пользователю, если ему это нужно. например пароль фтп. не хорошая идея?   -  person invictus    schedule 30.09.2013
comment
ХОРОШО. Вы можете использовать некоторые функции шифрования и дешифрования php, используя закрытый ключ для их хранения. Если пароли предназначены только для 1 вошедшего в систему пользователя, я бы сохранил случайный строковый ключ для этого пользователя, чтобы использовать его для шифрования и расшифровки паролей. Если у меня будет время, я попытаюсь написать код и опубликую его здесь, если он заработает.   -  person 3dgoo    schedule 01.10.2013
comment
это было бы прекрасно! благодарю вас. хотя попробую   -  person invictus    schedule 01.10.2013


Ответы (2)


Что вы можете сделать, так это создать Password DataObject с объектом Member, имеющим отношение один ко многим к объекту Password. Вы можете использовать соль зарегистрированного участника с двухсторонней функцией шифрования php для шифрования и расшифровки пароля.

В этом примере кода используется php mcrypt с солью члена для шифрования и расшифровки пароля.

Класс пароля имеет описание, URL-адрес, имя пользователя и пароль. Он содержит функцию для шифрования данной строки с использованием данного ключа. Он также содержит функцию расшифровки для расшифровки сохраненного пароля с использованием соли подключенного члена.

Класс пароля

<?php
class Password extends DataObject
{
    static $db = array (
        'Description' => 'Text', 
        'URL' => 'Text', 
        'Username' => 'Text', 
        'Password' => 'Text'
    );

    static $has_one = array (
        'Member' => 'Member'
    );

    public function decryptedPassword() {
        return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($this->Member()->Salt), base64_decode($this->Password), MCRYPT_MODE_CBC, md5(md5($this->Member()->Salt))), "\0");
    }

    public function encryptPassword($key, $password) {
        return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $password, MCRYPT_MODE_CBC, md5(md5($key))));
    }

}

Нам нужно расширить объект Member, чтобы иметь связь has_many с объектом Password:

MemberPasswordListExtension

<?php
class MemberPasswordListExtension extends DataExtension {

    private static $has_many = array(
        'Passwords' => 'Password'
    );
}

Это необходимо в вашей конфигурации, чтобы добавить расширение:

_config.php

...
Member::add_extension('Member', 'MemberPasswordListExtension');
...

Ниже представлена ​​форма для добавления пароля. При отправке мы шифруем пароль, используя соль члена и функцию шифрования из класса Password.

Контроллер страницы

...

public function AddPasswordForm() {
    // Create fields
    $fields = new FieldList(
        new TextField('Description'),
        new TextField('URL'),
        new TextField('Username'),
        new TextField('Password')
    );

    // Create actions
    $actions = new FieldList(
        new FormAction('AddPassword', 'Submit')
    );

    return new Form($this, 'AddPasswordForm', $fields, $actions);
}

public function AddPassword($data, $form) {
    if($member = Member::currentUser()) {
        $password = new Password();
        $form->saveInto($password);
        $password->MemberID = $member->ID;
        $password->Password = $password->encryptPassword($member->Salt, $password->Password);
        $password->write();
    }
    return $this->redirectBack();
}

...

В шаблоне страницы мы вызываем форму и перебираем пароли, сохраненные под этим пользователем. Мы отображаем имя пользователя, зашифрованный пароль и расшифрованный пароль, просто чтобы показать нам, что это сработало:

Шаблон Page.ss

...

<% if $CurrentMember %>
$AddPasswordForm
<% end_if %>

<% with $CurrentMember %>
<h3>Passwords</h3>
<% if $Passwords %>
<ul>
<% loop $Passwords %>
    <li>$Username $Password $DecryptedPassword</li>
<% end_loop %>
</ul>
<% else %>
<p>No passwords saved</p>
<% end_if %>
<% end_with %>

...

Это должно дать вам основу для того, что вы хотите сделать, и вы должны иметь возможность изменить ее в соответствии со своими потребностями.

Метод шифрования был взят из этого ответа stackoverflow: Простейшее двустороннее шифрование с использованием PHP< /а>

Вы можете легко заменить другой метод шифрования/дешифрования остальной частью этого кода по своему желанию.

person 3dgoo    schedule 02.10.2013
comment
Вау, большое спасибо. Вечером проверю, как приеду домой :) Результаты потом отпишусь. - person invictus; 02.10.2013
comment
Извините, я не мог проверить это до сих пор :/ Но в данный момент я настраиваю новую страницу с серебряной полосой, чтобы проверить это. Через 15-30 минут отпишусь о результатах - person invictus; 09.10.2013
comment
Хорошо, это работает как шарм :) Но это не соответствует моим потребностям. Пользователь не должен иметь возможности сохранять собственные пароли. У меня есть страница для каждого пользователя (клиента). И на этой странице я (админ) хочу хранить для них пароли. - person invictus; 09.10.2013
comment
Вам нужно будет только изменить способ ввода паролей, будь то через форму внешнего интерфейса, которая видна только членам администратора, или через администратора модели в задней части. Остальной код будет работать как есть. Я запрограммировал его таким образом, чтобы вы могли проверить, работает ли шифрование/дешифрование пароля. Дайте нам знать, если у вас возникнут трудности с программированием решения для сохранения паролей, которое вы выберете. - person 3dgoo; 10.10.2013
comment
Хорошо, я управляю этим с администратором модели. Но есть ли способ дать пользователю возможность редактировать предварительно выбранные записи? Я добавил флажок к каждой записи, когда он установлен, пользователь должен иметь возможность редактировать эту запись в интерфейсе, когда он нажимает кнопку редактирования позади нее. Это возможно? - person invictus; 10.10.2013

По умолчанию Silverstripe 3.x хранит пароли с необратимым соленым хэшем, используя Blowfish. Вы можете написать разные классы PasswordEncryptor для обработки другого поведения. См. различные классы в framework/security/PasswordEncryptor.php для примеров того, как это делается. Реализуйте PasswordEncryptor_Custom.php где-нибудь в своей кодовой базе (например, mysite/) и повторно реализуйте все функции.

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

person cryptopay    schedule 30.09.2013
comment
я думал, что пользователь может войти в систему, а затем получить доступ к своим паролям, ftp, mysql и т. д., и я не хочу хранить их в виде открытого текста в базе данных. Вы знаете безопасный способ решить эту проблему? - person invictus; 30.09.2013
comment
Поскольку вы не используете его для аутентификации, достаточно зашифровать пароль с помощью некоторого ключа перед его сохранением в базе данных. Используйте хэш пароля Blowfish в качестве ключа и извлеките из него соль, а затем добавьте соль с помощью секретного ключа, закодированного в приложении. Любой, кто скомпрометирует вашу базу данных, также потребует доступа к вашему веб-серверу для расшифровки ключа. Вам нужно будет декодировать и повторно кодировать всякий раз, когда пользователь меняет свой пароль. - person cryptopay; 01.10.2013