【问题标题】:Encryption and decryption in Laravel 5Laravel 5 中的加解密
【发布时间】:2018-09-05 07:01:21
【问题描述】:

我一直在寻找有关在 Laravel 中加密和解密值(如 VIN 号、员工身份证号、社会保险号等)的想法,最近在 Laravel 网站上找到了这个:https://laravel.com/docs/5.6/encryption

我的问题是,如何在刀片模板上打印解密的值?我可以看到通过控制器并设置一个变量,然后将其打印到 Blade,但我很好奇如何将解密的值打印到索引?就这样……

@foreach($employees as $employee)
{{$employee->decrypted value somehow}}
{{$employee->name}}
@endforeach

【问题讨论】:

  • 只需在视图中执行{{ decrypt($employee->ssn) }}。很简单。

标签: php laravel encryption laravel-5


【解决方案1】:

您可以使用 trait (app/EncryptsAttributes.php) 处理加密属性:

namespace App;

trait EncryptsAttributes {

    public function attributesToArray() {
        $attributes = parent::attributesToArray();
        foreach($this->getEncrypts() as $key) {
            if(array_key_exists($key, $attributes)) {
                $attributes[$key] = decrypt($attributes[$key]);
            }
        }
        return $attributes;
    }

    public function getAttributeValue($key) {
        if(in_array($key, $this->getEncrypts())) {
            return decrypt($this->attributes[$key]);
        }
        return parent::getAttributeValue($key);
    }

    public function setAttribute($key, $value) {
        if(in_array($key, $this->getEncrypts())) {
            $this->attributes[$key] = encrypt($value);
        } else {
            parent::setAttribute($key, $value);
        }
        return $this;
    }

    protected function getEncrypts() {
        return property_exists($this, 'encrypts') ? $this->encrypts : [];
    }

}

必要时在模型中使用它:

class Employee extends Model {

    use EncryptsAttributes;

    protected $encrypts = ['cardNumber', 'ssn'];

}

那么你就可以不用考虑加密来获取和设置属性了:

$employee->ssn = '123';
{{ $employee->ssn }}

【讨论】:

  • 您好,我实现了相同的方法,它与 getattribute 和 setattribute 一起使用,但不明白为什么要使用 attributesToArray
  • attributesToArray() 对于$model->toArray()$model->toJson() 是必需的。
【解决方案2】:

您可以在模型中创建自定义函数或an accessor

假设您的模型是Employee,而您的加密列是ssn。你可以这样做:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Employee extends Model
{
    // With a function
    public function decryptSsn()
    {
        return decrypt($this->attributes['ssn']);
    }

    // With an accessor
    public function getDecryptedSsnAttribute()
    {
        return decrypt($this->attributes['ssn']);
    }
}

如果你使用函数,你可以这样称呼它:

$employee->decryptSsn();

如果你使用访问器,你会这样称呼它:

$employee->decrypted_ssn;

【讨论】:

  • 当视图中一个简单的{{ decrypt($employee-&gt;ssn) }} 可以做到时,这似乎有点过于复杂了。
  • 这也行,是的。我建议使用功能/访问器以便于维护
  • 我不同意为每个加密属性设置单独的函数或访问器很容易维护。我更倾向于继承一个采用属性名称的函数(类或特征),并改为处理解密。
  • So if you plan to print it multiple times within the same request cycle, the accessor is better. - 怎么样?解密的值不会被缓存。那么有什么区别呢?
  • @fubar 关于未缓存的解密值是正确的。我认为它在第一次被调用时被附加到$attributes 数组中,并从那里被调用。经测试,我错了。至于更易于维护的功能,是的,具有特征或将另一种类型附加到$casts 将更易于维护。但是在许多视图中可能会出现decrypt($m-&gt;ssn),这是更容易维护的第一步。
【解决方案3】:

在模型中使用appends。更易于在任何地方使用,无需重复使用加密/解密助手

class Employee extends Model {
     protected $appends = [
           'encrypted_ssn_number',
     ];

     protected $hidden = ['ssn']; //if you want to hide from json of actual value of ssn

     public function getEncryptedSsnNumberAttribute()
     {
         return encrypt($this->ssn); // md5($this->ssn);  //bcrypt($this->ssn)
         // if $this->ssn not working, use $this->attribute['ssn']
     }
}

在模型中使用

{{ employee->encrypted_ssn_number }}

【讨论】:

    【解决方案4】:

    您可以在 app/trait Encryptable.php 中简单地创建一个自定义特征

    namespace App\Traits;
    use Illuminate\Support\Facades\Crypt;
    
    trait Encryptable
    {
    public function getAttribute($key)
    {
        $value = parent::getAttribute($key);
        if (in_array($key, $this->encryptable)) {
            try {
                $value = Crypt::decrypt($value);
            } catch (\Exception $e) {
                $value = null;
            }
        }
        return $value;
    }
    public function setAttribute($key, $value)
    {
        parent::setAttribute($key, $value);
        $value = $this->attributes[$key];
        if (in_array($key, $this->encryptable)) {
            $this->attributes[$key] = Crypt::encrypt($value);
        }
        return $this;
    }
    }
    

    在你的模型中只使用你想要加密的那些列。

    use App\Traits\Encryptable;
    class ABC extends Model {
    
    use Encryptable;
    
    protected $encryptable= ['name', 'description'];
    
    }
    

    【讨论】:

      【解决方案5】:

      app/Traits内创建文件Encryptable.php

      <?php
      
      namespace App\Traits;
      use Crypt;
      
      trait Encryptable
      {
      
           public function toArray()
           {
              $array = parent::toArray();
              foreach ($array as $key => $attribute) {
                  if (in_array($key, $this->encryptable) && $array[$key]!='') {
                      try {
                      $array[$key] = Crypt::decrypt($array[$key]);
                     } catch (\Exception $e) {
                     }
                  }
              }
              return $array;
          }
      
          public function getAttribute($key)
          {
              try {
                  $value = parent::getAttribute($key);
                  if (in_array($key, $this->encryptable) && $value!='') {
                      $value = Crypt::decrypt($value);
                      return $value;
                  }
                  return $value;
              } catch (\Exception $e) {
                  return $value;
              }
          }
      
          public function setAttribute($key, $value)
          {
              if (in_array($key, $this->encryptable)) {
                  $value = Crypt::encrypt($value);
              }
              return parent::setAttribute($key, $value);
          }
      }
      

      在你的模型中:

      use App\Traits\Encryptable;
      
      class Employee extends Model {
      
          use Encryptable;
          protected $encryptable = ['cardNumber', 'ssn'];
      
      }
      

      【讨论】:

        【解决方案6】:

        创建一个帮助文件,并在该文件中创建可从任何视图访问的函数。 按照此链接创建助手:https://laravelcode.com/post/how-to-create-custom-helper-in-laravel-55

        function decryptText($text) {
           return decrypt($text);
        }
        

        并像这样使用内部视图:

        @foreach($employees as $employee)
         {{decryptText($employee->encryptedText)}}
         {{$employee->name}}
        @endforeach
        

        【讨论】:

        • 完全不需要的功能。
        • 只有当你多次使用相同的逻辑并且你想全局修改解密和加密逻辑时才会使用full。否则,您必须修改到多个位置。它很方便,只需在一个地方更改就会选择整个应用程序。
        • decryptText($text)代替decrypt($text)有什么好处?
        • function decryptText($text) { return decrypt($text);// 如果你有多个逻辑像 //decrypt(anotherfunction(anotherfunction($text))) 像这样... }
        • 它被称为code bloat 你在那里做了什么。
        猜你喜欢
        • 2015-11-08
        • 2017-08-30
        • 2019-01-24
        • 1970-01-01
        • 2018-10-27
        • 2016-01-17
        • 2015-11-25
        • 1970-01-01
        • 2018-10-26
        相关资源
        最近更新 更多