1

我想将敏感信息(主要是密码)存储在 silverstripe 的数据对象中。数据需要加密存储在数据库中。如果我在模板中调用此字段,我需要解密数据。

但我不知道该怎么做。有人可以指出我正确的方向吗?

谢谢!

4

2 回答 2

2

您可以做的是创建一个Password DataObjectMember对象具有一对多关系的Password对象。您可以使用登录会员的 salt 和 2 路 php 加密功能来加密和解密密码。

此示例代码使用 php mcrypt 和成员 salt 来加密和解密密码。

密码类具有描述、url、用户名和密码。它包含一个使用给定密钥加密给定字符串的函数。它还包含一个解密函数,用于使用连接的成员 salt 解密存储的密码。

密码类

<?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 对象以与 Password 对象建立 has_many 关系:

MemberPasswordListExtension

<?php
class MemberPasswordListExtension extends DataExtension {

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

这是在您的配置中添加扩展所必需的:

_config.php

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

以下是添加密码的表格。在提交时,我们使用成员 salt 和 Password 类中的 encrypt 函数对密码进行加密。

Page_Controller

...

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的最简单的双向加密

您可以根据需要轻松地用此代码的其余部分替换不同的加密/解密方法。

于 2013-10-02T12:22:10.873 回答
1

默认情况下,Silverstripe 3.x 使用 Blowfish 以不可逆的加盐哈希存储密码。您可以编写不同的 PasswordEncryptor 类来处理其他行为。framework/security/PasswordEncryptor.php有关如何完成此操作的示例,请参阅中的各种类。在您自己的代码库(即 mysite/)中的某处实现 PasswordEncryptor_Custom.php 并重新实现所有功能。

请注意,这是非常不典型的,并且违背了安全的最佳实践。作为一般经验法则,您永远不应该向任何人提供明文密码。可逆密码加密本质上是不安全的,因为您实际上是将一个明文密码(用户的)替换为另一个(明文密钥)。使用不同的哈希值简单地重置密码总是更好的。

于 2013-09-30T00:05:13.513 回答