2.4 PhalApi 2.x 過(guò)濾器

2018-07-28 21:24 更新

過(guò)濾器

默認(rèn)可用的MD5簽名

基于很多同學(xué)對(duì)接口簽名驗(yàn)證比較陌生,PhalApi提供了一個(gè)基本版的接口驗(yàn)證服務(wù)。主要是基于md5進(jìn)行的簽名生成,這個(gè)只能作為一般性的參考。大家可以在此基礎(chǔ)上進(jìn)行調(diào)整延伸。

默認(rèn)情況下,在./config/di.php文件中去掉注釋便可開(kāi)啟此接口驗(yàn)證,即:

// 簽名驗(yàn)證服務(wù)
$di->filter = new \PhalApi\Filter\SimpleMD5Filter();

其驗(yàn)簽的算法如下(如注釋所示):

1、排除簽名參數(shù)(默認(rèn)是sign)
2、將剩下的全部參數(shù),按參數(shù)名字進(jìn)行字典排序
3、將排序好的參數(shù),全部用字符串拼接起來(lái)
4、進(jìn)行md5運(yùn)算

以下面的示例參數(shù)為例,即:

1、排除簽名參數(shù)(默認(rèn)是sign)
?service=Examples_CURD.Get&id=1


2、將剩下的全部參數(shù),按參數(shù)名字進(jìn)行字典排序
id=1
service=Examples_CURD.Get


3、將排序好的參數(shù),全部用字符串拼接起來(lái)
"1Examples_CURD.Get" = "1" + "Examples_CURD.Get"


4、進(jìn)行md5運(yùn)算
sign = 3ba5f5f03a90b2a648f5dd1df7387e26 = md5("1Examples_CURD.Get")


5、請(qǐng)求時(shí),加上簽名參數(shù)
?service=Examples_CURD.Get&id=1&sign=3ba5f5f03a90b2a648f5dd1df7387e26

下面是兩個(gè)調(diào)用示例,錯(cuò)誤請(qǐng)求下(即簽名失敗):

http://dev.phalapi.net/?service=Examples_CURD.Get&id=1&sign=xxx


返回:
{
    "ret": 406,
    "data": [],
    "msg": "非法請(qǐng)求:簽名錯(cuò)誤"
}

溫馨提示:簽名錯(cuò)誤情況下,可以查看日記獲得正確的sign,如:

2017-07-22 12:02:18|DEBUG|Wrong Sign|{"needSign":"3ba5f5f03a90b2a648f5dd1df7387e26"}

正常請(qǐng)求下(帶sign簽名):

http://dev.phalapi.net/?service=Examples_CURD.Get&id=1&sign=3ba5f5f03a90b2a648f5dd1df7387e26

如果不想使用sign作為關(guān)鍵的簽名參數(shù),可以在注冊(cè)時(shí)指定,如使用縮寫s:

$di->filter = new \PhalApi\Filter\SimpleMD5Filter('s');

白名單配置

對(duì)于不需要進(jìn)行簽名驗(yàn)證的接口服務(wù),可以使用白名單配置,通過(guò)框架自身實(shí)現(xiàn)對(duì)指定配置的接口服務(wù)排除。即調(diào)用的接口服務(wù),如果配置了白名單,則不調(diào)用過(guò)濾器。

接口服務(wù)白名單配置是:app.service_whitelist,即配置文件./config/app.php里面的service_whitelist配置,其默認(rèn)值是:

    'service_whitelist' => array(
        'Site.Index',
    ),

如源代碼里的注釋所示,配置的格式有以下四種。

類型 配置格式 匹配規(guī)則 示例及說(shuō)明
全部 *.* 匹配全部接口服務(wù)(慎用?。?/td> 如果配置了此規(guī)則,即全部的接口服務(wù)都不觸發(fā)過(guò)濾器。
方法通配 Site.* 匹配某個(gè)類的任何方法 即App\Api\Site接口類的全部方法
類通配 *.Index 匹配全部接口類的某個(gè)方法 即全部接口類的Index方法
具體匹配 Site.Index 匹配指定某個(gè)接口服務(wù) 即App\Api\Site::Index()

如果有多個(gè)生效的規(guī)則,按短路判斷原則,即有任何一個(gè)白名單規(guī)則匹配后就跳過(guò)驗(yàn)證,不觸發(fā)過(guò)濾器。

以下是更多的示例:

    'service_whitelist' => array(
        '*.Index',           // 全部的Index方法
        'Test.*',            // Api_Test的全部方法
        'User.GetBaseInfo',  // Api_User::GetBaseInfo()方法
    ),

配置好上面的白名單后,以下這些接口服務(wù)全部不會(huì)觸發(fā)過(guò)濾器:

// 全部的Index方法
?service=Site.Index
?service=User.Index


// Api_Test的全部方法
?service=Test.DoSth
?service=Test.Hello
?service=Test.GOGOGO


// Api_User::GetBaseInfo()方法
?service=User.GetBaseInfo

更好地建議

通常關(guān)于接口簽名這塊,我們還需要:

  • 1、為不同的接入方定義不同的密鑰和私鑰;
  • 2、如果業(yè)務(wù)需要,為各個(gè)接口、各個(gè)接入方分配調(diào)用權(quán)限;
  • 3、統(tǒng)一簽名參數(shù)的規(guī)則,可以配置在./config/app.php中的,如上面的簽名需要的參數(shù),我們可以追加統(tǒng)一的參數(shù)規(guī)則:
    /**
     * 應(yīng)用接口層的統(tǒng)一參數(shù)
     */
    'apiCommonRules' => array(
        'signature' => array('name' => 'signature', 'require' => true),
        'timestamp' => array('name' => 'timestamp', 'require' => true),
        'nonce' => array('name' => 'nonce', 'require' => true),
    ),

擴(kuò)展:實(shí)現(xiàn)你的簽名方式

如果我們需要實(shí)現(xiàn)簽名驗(yàn)證,只需要簡(jiǎn)單的兩步即可:

  • 1、實(shí)現(xiàn)過(guò)濾器接口 PhalApi\Filter::check();
  • 2、注冊(cè)過(guò)濾器服務(wù) PhalApi\DI()->filter

下面以大家熟悉的 微信驗(yàn)簽 為例,進(jìn)行示例說(shuō)明。

實(shí)現(xiàn)過(guò)濾器接口

通常我們約定返回ret = 402表示驗(yàn)證失敗,所以當(dāng)簽名失敗時(shí),我們可以返回ret = 402以告知客戶端簽名不對(duì)。根據(jù)微信的檢驗(yàn)signature的PHP示例代碼,我們可以快速實(shí)現(xiàn)自定義簽名規(guī)則,如:

// 文件 ./src/app/Common/SignFilter.php 
<?php
namespace App\Common;


use PhalApi\Filter;
use PhalApi\Exception\BadRequestException;


class SignFilter implements Filter
{
    public function check()
    {
        $signature = \PhalApi\DI()->request->get('signature');
        $timestamp = \PhalApi\DI()->request->get('timestamp');
        $nonce = \PhalApi\DI()->request->get('nonce');  


        $token = 'Your Token Here ...';
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode( $tmpArr );
        $tmpStr = sha1( $tmpStr );


        if ($tmpStr != $signature) {
            throw new BadRequestException('wrong sign', 1);
        }
    }
}

注冊(cè)過(guò)濾器服務(wù)

隨后,我們只需要再簡(jiǎn)單地注冊(cè)一下過(guò)濾器服務(wù)即可,在./config/di.php文件最后追加:

// 簽名驗(yàn)證服務(wù)
$di->filter = new App\Common\SignFilter();
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)