首先判断配置文件配置是否加密

#签名参数

'mcrypt'=>[

'is_open'=> true, #是否开启加密 默认true

'key' => 'mcrypt',

'iv' => '00000000'

],

#允许调用的接口 app_id 和 app_secret

'api_allow_access'=>[

'123456' => 'asdfghjkl',

],

如果is_open = true

把登录或其他提交的数据通过客户端加密 把app_id 加入api_param,app_secret拼接到json后面并MD5排列

#生成客户端的签名

private function _makeClientSign(&$api_param)

{

$api_auth = Yii::$app->params['API_AUTH'];

#加上接口鉴权

$api_param['app_id'] = $api_auth['api_id'];

#排序

ksort($api_param);

#转json

$json = json_encode($api_param);

#json 串 + api_secret

$json = $json.$api_auth['api_secret'];

return md5($json);

}

通过yii框架的param配置文件配置要跳转的路径

#api 接口域名

'url'=>[

#主域名

'domain' => '',

#接口的域名

'api_host' => '',

#接口的列表

'api_list' => [

#获取图片验证码的url

'getVcodeUrl' => '',

#登录接口

'login' => '',

#商品列表接口

'goodsList' => '',

#商品详情

'goodsDetial' => '',

#购物车session列表接口

'shopCartList' => '',

#获取购物车列表对应的商品信息

'getShopInfo' => '',

]

],

//发送api请求

public function sendApiRequest( $conf_name ,$api_param = [])

{

$api_url = $this->buildApiUrl($conf_name);

$mcrypt = Yii::$app->params['mcrypt'];

#验签

$api_des_data['sign'] = $this->_makeClientSign($api_param);

#对称加密

if($mcrypt['is_open'] == true){

if(!empty($api_param)){

$api_des_data['data'] = Des::encode(json_encode($api_param),$mcrypt['key'],$mcrypt['iv']);

}else{

$api_des_data['data'] = [];

}

}else{

$api_des_data['data'] = $api_param;

}

return $this->CurlPost($api_url , $api_des_data);

}

然后通过curlPOST 提交到api页面

在tp5框架也同理配置

//是否开启加密

'mcrypt'=>[

'is_open'=> true, #是否开启加密 默认true

'key' => 'mcrypt',

'iv' => '00000000'

],

然后建立构造方法initlize()

并直接判断配置项是否开启签名验证

如果开启验证就同样手法进行验证

验证通过则进行下一步 否则提示验签失败

其主要作用是防止信息被篡改;如果某个控制器方法不需要验签操作可以在api/common iniyialize 中加一个public属性

# 注 不需要验证签名的接口 TODO 必须小写

public $not_check_sign =[

'publics/getvcodeurl'

];

public function _initialize()

{

parent::_initialize();

$api_des = config('api.mcrypt');

$data = request()->post('data');

if($api_des['is_open'] == true){

if(!empty($data)){

$data_arr = json_decode(Des::decode($data,$api_des['key'],$api_des['iv']),true);

}else{

$data_arr = [];

}

$this->_data = $data_arr;

}else{

$this->_data = request()->post();

}

#签名

$clientSign = request()->post('sign');

#判断接口是否需要验签

$this->_inspectionSign($this->_data,$clientSign);

}

// 验签

private function _inspectionSign($data,$clientSign)

{

$controller = request()->controller();

$action = request()->action();

$url = $controller.'/'.$action;

if(in_array(strtolower($url),$this->not_check_sign)){

$serverSign = $this->_makeServerSign($data);

if($clientSign != $serverSign){

$this->error('数据验签失败');

}

}

}

// 生成服务器的签名

private function _makeServerSign($data)

{

#排序

ksort($data);

#取出api_id

if(empty($data['app_id'])){

$this->error('鉴权失败');

}

# 根据app_id 取出对应的 app_secret

$api_allow_access = config('api.api_allow_access');

#如果传过来的app_id 不存在 提示鉴权失败 函数:array_key_exisets() 检查给定的键名或索引是否存在于数组中

if(!array_key_exists($data['app_id'],$api_allow_access)){

$this->error('鉴权失败');

}

#转json

$json = json_encode($data);

return md5($json.$api_allow_access[$data['app_id']]);

}

**注意** :两个配置文件的iv必须相同,否则会出现验签失败;

tp5 Des类如下

namespace Des;

/**

* des Helper Class

*/

class Des

{

/**

* DES加密 (需要打开php.ini的extension=php_mcrypt.dll)

* @param string $input

* @param string $key

* @return string

*/

public static function encode($input, $key, $iv)

{

//填充算法 PKCS7

$input = DES::addPKCS7Padding($input);

//打开算法和模式对应的模块 加密算法 3DES 加密模式 CBC

$td = mcrypt_module_open(MCRYPT_3DES, '', 'cbc', '');

//设置加密的key 以及初始化向量

mcrypt_generic_init($td, $key, $iv);

//加密

$encrypted_data = mcrypt_generic($td, $input);

//对加密模块进行清理工作

mcrypt_generic_deinit($td);

//关闭加密模块

mcrypt_module_close($td);

// var_dump(base64_encode($encrypted_data) );exit;

//加加密的数据进行base64编码

$encode = trim(chop(base64_encode($encrypted_data)));

return $encode;

}

/**

* DES解密

* @param string $input

* @param string $key

* @return string

*/

public static function decode($input, $key, $iv)

{

//反编码

$input = trim(chop(base64_decode($input)));

//打开算法和模式对应的模块 加密算法 3DES 加密模式 CBC

$td = mcrypt_module_open(MCRYPT_3DES, '', 'cbc', '');

//设置加密的key 以及初始化向量

mcrypt_generic_init($td, $key, $iv);

//解密的数据

$decrypted_data = mdecrypt_generic($td, $input);

//对加密模块进行清理工作

mcrypt_generic_deinit($td);

//关闭加密模块

mcrypt_module_close($td);

//去除 PKCS7 填充

$decrypted_data = DES::stripPKSC7Padding($decrypted_data);

return $decrypted_data;

}

//PKCS7填充

private static function addPKCS7Padding($source)

{

//获得加密算法的分组大小 8

$block = mcrypt_get_block_size(MCRYPT_3DES, 'cbc');

//计算要填充的长度

$pad = $block - (strlen($source) % $block);

//填充字符串

if ($pad <= $block) {

//chr — 返回指定的字符 ASCII

$char = chr($pad);

//填充字符串

$source .= str_repeat($char, $pad);

}

return $source;

}

//去除PKCS7的填充

private static function stripPKSC7Padding($source)

{

//获得加密算法的分组大小 8

$block = mcrypt_get_block_size(MCRYPT_3DES, 'cbc');

$char = substr($source, -1, 1);

//返回字符的 ASCII 码值

$num = ord($char);

if ($num > 8) {

return $source;

}

$len = strlen($source);

for ($i = $len - 1; $i >= $len - $num; $i--) {

if (ord(substr($source, $i, 1)) != $num) {

return $source;

}

}

$source = substr($source, 0, -$num);

return $source;

}

}

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐