淺談API開發安全之生成sign(一)

在對於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校驗(二)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章