【问题标题】:Store sensitiv data in Silverstripe 3.1在 Silverstripe 3.1 中存储敏感数据
【发布时间】:2013-09-29 14:16:53
【问题描述】:

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

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

谢谢!

【问题讨论】:

  • 使用可逆哈希存储密码数据有点违背它的安全理念?一个解决方案可能是使用加密密钥,但如果该密钥被泄露,您的所有数据都会被泄露,尤其是因为该密钥需要始终被服务器访问,因此存在风险......
  • 为什么要在模板中调用它?您想向用户显示密码吗?还是只检查密码是否输入正确?
  • 如果用户需要,我想将其展示给用户。例如 ftp 密码。不是个好主意?
  • 好的。您可以使用一些使用私钥的 php 加密和解密函数来存储它们。如果密码仅适用于 1 个登录用户,那么我将针对该用户存储一个随机字符串密钥,用于加密和解密密码。如果我有时间,我会尝试编写一些代码,如果我能正常工作,我会在这里发布。
  • 那太好了!谢谢你。我会尝试一下

标签: php mysql silverstripe


【解决方案1】:

您可以做的是创建一个PasswordDataObject,其中Member 对象与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 答案: Simplest two-way encryption using PHP

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

【讨论】:

  • 哇,非常感谢。我今晚一到家就测试:) 之后我会发布我的结果。
  • 抱歉,直到现在我才能对其进行测试:/ 但目前我正在设置一个新的 silverstripe 页面来测试它。我会在大约 15 - 30 分钟后发布我的结果
  • 很好,它就像一个魅力:) 但它不符合我的全部需求。用户不应该能够保存自己的密码。我为每个用户(客户端)提供了一个页面。在这个页面上,我(管理员)想为他们存储密码。
  • 您只需要更改输入密码的方式,无论是通过仅对管理员成员可见的前端表单,还是通过后端的模型管理员。其余代码将按原样工作。我是这样编程的,所以你可以测试密码加密/解密是否有效。如果对您选择的密码保存解决方案进行编程有任何困难,请告诉我们。
  • 好的,我正在使用模型管理员管理它。但是有没有办法让用户可以编辑预先选择的条目?我为每个条目添加了一个复选框,当它被选中时,用户应该能够在前端编辑这个条目,当他点击它后面的编辑按钮时。这可能吗?
【解决方案2】:

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

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

【讨论】:

  • 我的想法是,用户可以登录,然后他可以访问他的密码、ftp、mysql 等,我不会将它们作为明文存储在数据库中。你知道解决这个问题的安全方法吗?
  • 由于您不使用它进行身份验证,因此在将密码存储到数据库之前使用一些密钥对密码进行加密就足够了。使用 Blowfish 密码哈希作为密钥并从中提取盐,然后使用编码到应用程序中的密钥进一步对其进行盐化。任何破坏您的数据库的人也需要访问您的网络服务器来解密密钥。每当用户更改密码时,您都需要进行解码和重新编码。
猜你喜欢
  • 2017-09-05
  • 2020-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-15
  • 1970-01-01
  • 1970-01-01
  • 2021-03-27
相关资源
最近更新 更多