在對於API的開發中,最讓人頭疼的就是接口數據暴露,讓一些有心之人抓包之後惡意請求,那麼如何解決這一弊端呢?自然而然的我們就想到了加密 ,那我們又如何加密,如何解密,才能使之有最安全的效率呢?這是一個值得我們深思的問題,帶着這些問題,我們來嘗試着 一一解決問題
首先加密校驗是需要在每次請求的時候,都要去做的,所以我們需要寫一個公共類,讓其他類來繼承,暫定這個類就爲 Common
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2019/8/15
* Time: 15:00
*/
namespace app\index\controller;
use think\Controller;
class Common extends Controller
{
public function _initialize(){
$this->checkRequestAuth();
}
public function checkRequestAuth(){
##獲取頭信息
$header = request()->header();
halt($header);
}
}
上面代碼很簡單 我們就是單純的獲取一下header裏面的信息 爲什麼要獲取header而不是body裏的信息呢 可能header好聽吧(手動滑稽), 那麼既然我們獲取的是header裏面的內容,那麼這裏面去放什麼內容,才能是我們更好的校驗呢,這就需要和前端小姐姐共同商議啦,當然,我這邊已經確定,我們需要的參數啦
sign: 參數加密後生成的簽名
version: APP版本號
app_type: APP類型 ios android之類
did: 唯一標識ID
model: 類似手機型號之類的值
在我們定義好header裏面的內容之後,那麼我們就要開始在Common類裏面大展拳腳了 ,我們需要了解 sign 加密是需要客戶端去做的 ,解密是需要我們服務端來做的,但是正常流程來說,是需要我們服務端測試加密解密無誤後,纔開放接口給客戶端的,所以這裏,我們必須去實現加密功能,接下來,我們去搞一波加密算法,我們使用 AES加密算法來進行測試
<?php
namespace app\common\lib;
/**
* aes 加密 解密類庫
* @by singwa
* Class Aes
* @package app\common\lib
*/
class Aes {
/**
* var string $method 加解密方法,可通過openssl_get_cipher_methods()獲得
*/
protected $method;
/**
* var string $secret_key 加解密的密鑰
*/
protected $secret_key;
/**
* var string $iv 加解密的向量,有些方法需要設置比如CBC
*/
protected $iv;
/**
* var string $options (不知道怎麼解釋,目前設置爲0沒什麼問題)
*/
protected $options;
/**
* 構造函數
*
* @param string $key 密鑰
* @param string $method 加密方式
* @param string $iv iv向量
* @param mixed $options 還不是很清楚
*
*/
public function __construct($key, $method = 'AES-128-ECB', $iv = '', $options = 0)
{
// key是必須要設置的
$this->secret_key = isset($key) ? $key : config('app.aeskey');
$this->method = $method;
$this->iv = $iv;
$this->options = $options;
}
/**
* 加密方法,對數據進行加密,返回加密後的數據
*
* @param string $data 要加密的數據
*
* @return string
*
*/
public function encrypt($data)
{
return openssl_encrypt($data, $this->method, $this->secret_key, $this->options, $this->iv);
}
/**
* 解密方法,對數據進行解密,返回解密後的數據
*
* @param string $data 要解密的數據
*
* @return string
*
*/
public function decrypt($data)
{
return openssl_decrypt($data, $this->method, $this->secret_key, $this->options, $this->iv);
}
}
祕鑰寫在配置文件裏
return [
'aeskey' => 'asdasd4wq5646', #AES祕鑰 服務端必須和客戶端保持一致
'method' => 'AES-128-ECB',
'iv' => '',
'options' => '0',
];
現在我們的加密算法已經準備就緒,下來我們需要做的就是,將傳進來的參數進行整合,加密後,返回,這樣我們的 sign就生成了,因爲生成sign屬於鑑權類型,所以我們 在app\common\lib下新建 IAuth 類
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2019/8/15
* Time: 16:06
*/
namespace app\common\lib;
use app\common\lib\Aes;
class IAuth
{
/**
* 生成每次請求的sign
* @param array $data
* @return string
*/
public static function setSign($data = []){
## 1 按字典進行相對應的排序
ksort($data);
## 2 轉換爲&拼接的參數
$string = http_build_query($data);
## 3 通過 aes 來加密
$string = (new Aes())->encrypt($string);
return $string;
}
}
生成sign類寫好了,我們去測試下
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2019/8/15
* Time: 15:03
*/
namespace app\index\controller;
use app\common\lib\Aes;
use app\common\lib\IAuth;
class Test extends Common
{
public function index(){
## 加密部分
// $data = [
// 'did'=>1,
// 'version'=>"1.1.0",
// ];
//
// halt(IAuth::setSign($data));
#解密部分
$str = "g/1A3h+7XZZrdc3Gw1yEJBEAWTiKEm/veV5vMlyFLpc=";
halt((new Aes())->decrypt($str));
}
}
加密解密都沒有問題 ,生成sign成功。
如需瞭解更多,可以查看下一篇文章,將講解如何對sign進行校驗淺談API開發安全之sign校驗(二)