Laravel Eloquent - 在调用时加密/解密数据

15

我可以使用Crypt来加密/解密我的数据。我想加密数据库中的一些信息(例如姓名、电子邮件、电话号码等)。

假设我想加密所有内容,我希望能够通过后台自动执行此操作,这可以通过覆盖createsave函数来实现:

// 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))。

这种做法可能吗?如果不行,我考虑创建一个辅助函数 decrypt()

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方式”来实现这个功能就更好了。

2个回答

18

加密所有内容并不是明智的选择。例如,您永远不希望加密主键;这甚至没有意义。同样,您可能不希望加密日期字段;否则,您将失去对它们执行任何 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的访问器功能,您需要对其进行进一步的调整。


这个不起作用。例如,当我使用User::find(1)时,在getAttribute()中被调用的唯一$keyidpivot - Kousha
我使用return Response::json(User::find($id))作为示例,getAttribute从未被调用。如果我执行User::find($id)->name,那么它会被调用。但是我需要从API返回JSON,所以我需要让JSON正常工作?即使是User::find($id)->toJson()也不会调用它。 - Kousha
太好了!谢谢你!我有一个小建议,我认为你需要键入Crypt::decrypt($this->attributes[$key]);而不是Crypt::decrypt($this->attributes($key));因为$this->attributes是一个数组而不是函数。 - Kousha
如果我使用查询构建器而不是 Eloquent,是否有其他解决方案? - rajatsaurastri

1

值得一提的是,Elocrypt 是 Laravel 4 的一个库。它是一个更为详细的解决方案,工作方式相同。如果您使用的是 Laravel 5,请改用 Elocrypt 5


https://github.com/austinheap/laravel-database-encryption 看起来也不错。 - Ryan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接