PHP接口开发签名验证原理详解

 更新时间:2016年11月25日 17:18  点击:2050
接口签名现在在应用开发中我们通常会用到了,像做支付接口时就必须要用到接口签名了,我们下面来看一个简单的在app应用中的接口签名实现原理了。

接口开发是各系统之间对接的重要方式,其数据是通过开放的互联网传输,对数据的安全性要有一定要求。为了提高传输过程参数的防篡改性,签名sign的方式是目前比较常用的方式。

我这里介绍一种方式,是目前国内互联网公司常用的一种方式,其中淘宝的支付宝支付接口、淘宝开放平台接口、腾讯开放平台等应用的一种方式。

 一、签名参数sign生成的方法

第1步: 将所有参数(注意是所有参数),除去sign本身,以及值是空的参数,按参数名字母升序排序。
第2步: 然后把排序后的参数按参数1值1参数2值2…参数n值n(这里的参数和值必须是传输参数的原始值,不能是经过处理的,如不能将"转成”后再拼接)的方式拼接成一个字符串。
第3步: 把分配给接入方的验证密钥key拼接在第2步得到的字符串前面。
第2步: 在上一步得到的字符串前面加上验证密钥key(这里的密钥key是接口提供方分配给接口接入方的),然后计算md5值,得到32位字符串,然后转成大写.
第4步: 计算第3步字符串的md5值(32位),然后转成大写,得到的字符串作为sign的值。

举例:

假设传输的数据是/interface.php?sign=sign_value&p2=v2& p1=v1&method=cancel&p3=&pn=vn(实际情况最好是通过post方式发送),

其中sign参数对应的sign_value就是签名的值。

第一步,拼接字符串,首先去除sign参数本身,然后去除值是空的参数p3,剩下p2=v2&p1=v1&method=cancel& amp;pn=vn,然后按参数名字符升序排序,method=cancel&p1=v1&p2=v2&pn=vn.

第二步,然后做参数名和值的拼接,最后得到methodcancelp1v1p2v2pnvn
第三步,在上面拼接得到的字符串前加上验证密钥key,我们假设是abc,得到新的字符串abcmethodcancelp1v1p2v2pnvn

第四步,然后将这个字符串进行md5计算,假设得到的是abcdef,然后转为大写,得到ABCDEF这个值即为sign签名值。

注意,计算md5之前请确保接口与接入方的字符串编码一致,如统一使用utf-8编码或者GBK编码,如果编码方式不一致则计算出来的签名会校验失败。

二、签名验证方法:

根据前面描述的签名参数sign生成的方法规则,计算得到参数的签名值,和参数中通知过来的sign对应的参数值进行对比,如果是一致的,那么就校验通过,如果不一致,说明参数被修改过。

例子

 

 代码如下 复制代码
<?php
//header('Content-Type: text/xml; charset=utf-8');
include_once(dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'phpsec'.DIRECTORY_SEPARATOR.'Math'.DIRECTORY_SEPARATOR.'BigInteger.php');
include_once(dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'phpsec'.DIRECTORY_SEPARATOR.'Crypt'.DIRECTORY_SEPARATOR.'AES.php');
include_once(dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'phpsec'.DIRECTORY_SEPARATOR.'Crypt'.DIRECTORY_SEPARATOR.'RSA.php');
//密文
$crypttext = 'v66YKULHFld2JElhm/J9qik2Edr1JHdZIc/k/OesU2GbTX2usXyvF4jGvzvoihrrE8FsfKmllmjsMIjO5fdrS/FD20bYFii4JW3BO3bzshXmz6AEs2DWwG4sK9mNojfOC0IsMoV311X5/JlgUoQXkDy4F5HHpYE9d/xGb0g2XE/hnGSSy2cpQcvQtBlBmixwSckNhsEG92lovlOz8ULwkqG5o7x+qB7P/EMII/WaFAXBJXDXvZX7lmGcOgon6wLhKJLGXorP6BIxOg6LGc6Ux7BAt3i9+0lujNgxIq/sDsl23hsr3yOUpV5C5a813nrHx4HJyd/hBT1UvIUml+eTmJwWCpSfs2cvxIUr0CE57JAZVyXjK13shK3IsZHLPPsm/JcDCrdy0Co/d5uIGJAdzXdsQ56xsju+tlvnA1J6yq2tDIfYK/x6k911A5WXLKYxztD1nq+bTYN3Gv/WFfrzVtgWQBrh06ihS2cwvna0S9EV/YPmhnAjJmrX4trNr9NXQ9xaZaW4lGRg87U5QDV+nQjj1THk0XHFc69N9g2+DsAGyEs9tK6U0ZQ72hJZqZhBCDH1UKw0PLyIhJdxpgPPOWGp8/QVVU2julTeKunvgAAEc3n+GoZfqjsCDi1S6T2MTnjWYWNoFRBhvEZFD/revgpasTOzDQa5NqR1B+mUF70r6uw6MWLJ7cT9Tz3jq+CA';
$aeskey = base64_decode('qZe60QZFxuirub2ey4+7+Q==');
//AES解密,采用ECB模式
$aes = new Crypt_AES(CRYPT_MODE_ECB);
//设置AES密钥
$aes->setKey($aeskey);
//解密AES密文
$plaintext = $aes->decrypt(base64_decode($crypttext));
echo $plaintext;
echo '<hr />';
//AES加密明文
//echo $aes->encrypt($plaintext);
//rsa公钥
$publickey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCffOeIVYut9jW5w1L5uKX4aDvd837a8JhaWm5S8YqNQfgEmfD9T+rDknXLqMT+DXeQAqGo4hBmcbej1aoMzn6hIJHk3/TfTAToNN8fgwDotHewsTCBbVkQWtDTby3GouWToVsRi1i/A0Vfb0+xM8MnF46DdhhrnZrycERBSbyrcwIDAQAB';
//echo base64_decode($publickey);
//rsa签名
$signature = 'XHin4uUFqrKDEhKBD/hQisXLFFSxM6EZCvCPqnWCQJq3uEp3ayxmFuUgVE0Xoh4AIWjIIsOWdnaToL1bXvAFKwjCtXnkaRwUpvWrk+Q0eqwsoAdywsVQDEceG5stas1CkPtrznAIW2eBGXCWspOj+aumEAcPyYDxLhDN646Krzw=';
//echo base64_decode($signature);
$rsa = new Crypt_RSA();
//设置RSA签名模式 CRYPT_RSA_SIGNATURE_PSS or CRYPT_RSA_SIGNATURE_PKCS1
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
//var_dump($rsa->createKey());
//生成RSA公钥、私钥
//extract($rsa->createKey());
//使用RSA私钥生成签名
//$rsa->loadKey($privatekey);
//$signature = $rsa->sign($plaintext);
//使用RSA公钥验证签名
echo $plaintext;
$rsa->loadKey(base64_decode($publickey));
echo $rsa->verify($plaintext, base64_decode($signature)) ? 'verified' : 'unverified';
echo '<hr />';
//生成RSA公钥、私钥
//var_dump($rsa->createKey());
extract($rsa->createKey());
//使用RSA私钥加密数据
$rsa->loadKey($privatekey);
$ciphertext = $rsa->encrypt($plaintext);
//使用RSA公钥解密数据
$rsa->loadKey($publickey);
echo $rsa->decrypt($ciphertext);
字符串截取我们这里有简单的办法,通常如果只对于简单的可以使用substr函数了,如果要删除字符串中的字符我们也可以使用substr函数了,下面来看看。


修复了一个获取控制器名称方法的bug

控制器的名称都是使用act结尾,使用过程中要删除act。

1。原来的方法

//使用替换act的方法获取控制器名称,很显然当控制器的名称出现act三个字符的时候都会被替换掉产生bug

$actName = str_replace( 'act', '', 'ad_client_contactact');

控制器名称 ad_client_cont

2。修复后的方法

//从结尾删除三个字符串

$actName = substr('ad_client_contactact',0,-3);

控制器名称ad_client_contact


1、从第4个字符开始截取到字符串末尾,类似asp中的left:

<?php $str = "www。icoa。cn"; echo substr($str,4); ?>

输出: icoa。cn

2、PHP substr函数从右边截取3个字符,类似asp中的right:

<?php $str = "www。icoa。cn"; echo substr($str,-3); ?>

输出:。cn

3、PHP substr函数从第4个字符开始截取3个字符:

<?php $str = "www。icoa。cn"; echo substr($str,4,3); ?>

输出:ico

4、有时我们知道一个字符串的开始和结尾,中间是不定长的字符,这时除了用PHP substr函数的正则外我们还可以用substr实现(当然要得到中间的字符方法有N种,在此只是举例substr的应用):

本例去掉开头4个字符和结尾3个字符,输出中间的字符串:

<?php $str = "www。icoa。cn"; echo substr($str,4,-3); ?>

输出:icoa
5、对中文看看
$a="直的、竖的、横的、方的、"
$a=substr($a,0,-1);
输出结果为:直的、竖的、横的、方的

6、查找指定字符串并删除

$a = "abcababa"; 
$count=strpos($a,"ab"); 
$str=substr_replace($a,"",$count,2);
输出结果:cababa


代码虽短,但也算是一个小算法!


7、删除字符串中任何字符的函数

function delStr($start, $end, $orgenStr) 

{ 

  //读取要删除字符位置的前一部分字符串,并赋值给$temp  

  //strpos读取字符第一次出现的位置  

  //substr读取指定开始与结束位置的子字符串  

  //echo $before."—". $last;  

  $temp=$orgenStr; 

  while(strpos($temp, $start) && strpos($temp, $end)){ 

  $temp=substr($temp, 0, strpos($temp, $start)).substr($temp,strpos($temp, $end)+strlen($end));; 

  //读取要删除字符位置的后一部分字符串,然后将前后部分连接,并赋值给$temp  

  //返回最后是字符串  

  } 

  return $temp; 

} 

//应用实例  

$a="aaaa12345678bbbbtttttttttttttttttttttaaaa12345678bbbb 

kkkkkkkkkkkkaaaa12345678bbbbttttttttttttttttttttt"; 

$b="1234"; 

$c="5678"; 

echo delStr($b,$c,$a);

本文章为各位介绍一篇关于解决PHP报错ZipArchive library is not enabled异常的方法,希望文章能够对大家有帮助。

   今天在Linux底下上传Excel文件时,抛出“ZipArchive library is not enabled” 的异常。而我在本地的windows下的代码则是运行正常的。
 
      原因是:在Linux下没有php_zip.dll这个文件(有也不会起作用的),所以需要重新编译一下php的zip模块。
    
     在Unix/Linux下的解决办法 :
  
      1、依次运行如下命令:

 

      cd /usr/src 

      wget 
http://pecl.php.net/get/zip
   (默认会在线下载最新版本的)

      tar zxvf zip.x.x.tgz   (所下载的包名)

      cd zip-1.x.x 

      /usr/bin/phpize    (对应的phpize路径 find / -name phpize 出来结果/usr/bin/phpize)

      ./configure --with-php-config=/usr/bin/php-config (对应的php-config路径)

      make 

      make instal


 
      2、查看生成的模块路径(安装完之后,屏幕上会提示zip.so的位置):
     cd /usr/lib/php/modules/ (对应的extensions路径 /usr/lib/php/modules/)
 
      3、修改php.ini
      增加 extension=zip.so
    然后同样在php.ini文件中,将zlib.output_compression = Off 改为 zlib.output_compression = On ;
 
      4、最后再重启一下Apache:./apachectl restart ;
    
      这个针对php的zip模块就安装完成了,能够在php中使用ZipArchive类了。
 
      附:在Windows下的解决办法就比较简单了 :
 
     1、在php.ini文件中,将extension=php_zip.dll前面的分号“;”去除
  然后同样在php.ini文件中,将 zlib.output_compression = Off 改为 zlib.output_compression = On ;
 
     2、重启Apache服务器。

提取URL是需要通过正则来匹配了,其实我们就是正则来获取字符串中的url地址了,具体的实现方法如下文所示。

这篇文章主要介绍了php提取字符串中网站url地址的方法,可通过正则匹配查找并提取出URL地址,需要的朋友可以参考下

$postInfo['answer2'] ='学习php的方法很多,通过搜索引擎可以搜索到很多资料,当然也可以进入PHP二次开发博客学习哦:http://www.111cn.net,一起交流学'; 
 

preg_match_all("/http:[\/]{2}[a-z]+[.]{1}[a-z\d\-]+[.]{1}[a-z\d]*[\/]*[A-Za-z\d]*[\/]*[A-Za-z\d]*/",$postInfo['answer2'],$array2);  

  

print_r($array2);  

  

if(!emptyempty($array2[0]))  

{  

 foreach ($array2[0] as $k=>$v){  

  $postInfo['answer2'] = str_replace($array2[0][$k],'',$postInfo['answer2'] );  

 }  

}

输出结果:

    (  

        [0] => Array  

            (  

                [0] => http://www.111cn.net

            )  

    )

简易信息聚合(也叫聚合内容)是一种RSS基于XML标准,在互联网上被广泛采用的内容包装和投递协议。RSS(Really Simple Syndication)是一种描述和同步网站内容的格式,使用非常的多,下面我们来介绍在生成rss时pubDate所需日期时间格式的方法

SS / ATOM 的格式要产生都很简单, 麻烦的是日期格式的产生(RSS => pubDate, ATOM => created).

发现 PHP Date 有提供这些需要的相关全域变量可以使用:(PHP 5.1.1 以后开始支援这些全域变量)

 echo DATE_RSS; // D, d M Y H:i:s O

    echo DATE_ATOM; // Y-m-d\TH:i:sP

    echo date(DATE_RSS); // Wed, 23 Apr 2008 19:27:19 +0800

    echo date(DATE_ATOM); // 2008-04-23T19:27:38+08:00

如果是 MySQL timestamp/datetime format 直接拉出来的资料, 就可以直接使用:

 date(DATE_RSS, ($MYSQL_DATETIME_DATA));

目前支持的日期全域变量有以下:

 DATE_ATOM: Atom  Atom (example: 2005-08-15T15:52:01+00:00)

    DATE_COOKIE: HTTP Cookies (example: Monday, 15-Aug-05 15:52:01 UTC)

    DATE_ISO8601: ISO-8601 (example: 2005-08-15T15:52:01+0000)

    DATE_RFC822: RFC 822 (example: Mon, 15 Aug 05 15:52:01 +0000)

    DATE_RFC850: RFC 850 (example: Monday, 15-Aug-05 15:52:01 UTC)

    DATE_RFC1036: RFC 1036 (example: Mon, 15 Aug 05 15:52:01 +0000)

    DATE_RFC1123: RFC 1123 (example: Mon, 15 Aug 2005 15:52:01 +0000)

    DATE_RFC2822: RFC 2822 (Mon, 15 Aug 2005 15:52:01 +0000)

    DATE_RFC3339: Same as DATE_ATOM

    DATE_RSS: RSS (Mon, 15 Aug 2005 15:52:01 +0000)

    DATE_W3C: World Wide Web Consortium (example: 2005-08-15T15:52:01+00:00)

PHP 预定义的日期格式

自 PHP 5.1.1 起定义有以下常量来提供标准日期表达方法,可以用于日期格式函数

 echo DATE_RSS; // D, d M Y H:i:s O

    echo DATE_ATOM; // Y-m-d\TH:i:sP

    echo date(DATE_RSS); // Wed, 23 Apr 2008 19:27:19 +0800

    echo date(DATE_ATOM); // 2008-04-23T19:27:38+08:00

虽然格式简单, 但用PHP内的预定义格式岂不更加方便.

目前PHP所有支持的日期格式:

DATE_ATOM: Atom  Atom (example: 2005-08-15T15:52:01+00:00)

    DATE_COOKIE: HTTP Cookies (example: Monday, 15-Aug-05 15:52:01 UTC)

    DATE_ISO8601: ISO-8601 (example: 2005-08-15T15:52:01+0000)

    DATE_RFC822: RFC 822 (example: Mon, 15 Aug 05 15:52:01 +0000)

    DATE_RFC850: RFC 850 (example: Monday, 15-Aug-05 15:52:01 UTC)

    DATE_RFC1036: RFC 1036 (example: Mon, 15 Aug 05 15:52:01 +0000)

    DATE_RFC1123: RFC 1123 (example: Mon, 15 Aug 2005 15:52:01 +0000)

    DATE_RFC2822: RFC 2822 (Mon, 15 Aug 2005 15:52:01 +0000)

    DATE_RFC3339: Same as DATE_ATOM

    DATE_RSS: RSS (Mon, 15 Aug 2005 15:52:01 +0000)

    DATE_W3C: World Wide Web Consortium (example: 2005-08-15T15:52:01+00:00)

 

生成rss例子

header("Content-type: application/xml");  //定义header头,以防止chrome内核的浏览器不支持rss订阅,如果不支持就输出xml格式的文件
/**
 * 查询数据库,获取要输出rss的数据
 */
$database = "nameofthedatabase";
$dbconnect = mysql_pconnect(localhost, dbuser, dbpassword);
mysql_select_db($database, $dbconnect);
$query = "select link, headline, description from `headlines` limit 15";
$result = mysql_query($query, $dbconnect);
while ($line = mysql_fetch_assoc($result)) {
    $return[] = $line;
}
$now = date("D, d M Y H:i:s T");
$output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>
            <rss version=\"2.0\">
                <channel>
                    <title>山东道路交通安全网-$lanmu</title>
                    <link>http://sdjtaq.cn/rss</link>
                    <description>Latest 100 articles of $lanmu</description>
                    <pubDate>$now</pubDate>
                    <lastBuildDate>$now</lastBuildDate>
                    <docs>http://someurl.com</docs>
                    <managingEditor>810706080@qq.com</managingEditor>
                    <webMaster>810706080@qq.com</webMaster>
            ";
foreach ($artList as $line) {
    $date = strtotime($line['add_time']); //将数据库的时间格式化成时间戳
    $output .= "<item> \n"
            . "<title>" . $line['title'] . "</title>\n"
            . " <link>http://sdjtaq.cn/aq_show_" . $line['id'] . ".html</link>\n"
            . "<description><![CDATA[" . $line['zhaiyao'] . "]]></description>\n"
            . "<pubDate>" . date("D, d M Y H:i:s O", $date) . "</pubDate>\n"
            . "</item>\n";
}
$output .= "</channel>\n</rss>";
echo $output;

[!--infotagslink--]

相关文章

  • c# 三种方法调用WebService接口

    这篇文章主要介绍了c# 三种方法调用WebService接口的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-07
  • 浅谈TypeScript 索引签名的理解

    这篇文章主要给大家分享的是TypeScript 索引签名的理解,索引签名由方括号中的索引名称及其类型组成,后面是冒号和值类型:{ [indexName: KeyType]: ValueType }, KeyType 可以是一个 string、number 或 symbol,而ValueType 可以是任何类型,下面就俩简单了解一下吧...2021-10-15
  • vue接口请求加密实例

    这篇文章主要介绍了vue接口请求加密实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-12
  • Django def clean()函数对表单中的数据进行验证操作

    这篇文章主要介绍了Django def clean()函数对表单中的数据进行验证操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-09
  • JavaScript实现密码框输入验证

    这篇文章主要为大家详细介绍了JavaScript实现密码框输入验证,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-10-01
  • Nest.js 授权验证的方法示例

    这篇文章主要介绍了Nest.js 授权验证的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-22
  • el-table树形表格表单验证(列表生成序号)

    这篇文章主要介绍了el-table树形表格表单验证(列表生成序号),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-01
  • C#简单了解接口(Interface)使用方法

    这篇文章主要介绍了C#简单了解接口(Interface)使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-12-08
  • SpringBoot接口接收json参数解析

    这篇文章主要介绍了SpringBoot接口接收json参数解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-19
  • C# Rx的主要接口深入理解

    这篇文章主要介绍了C# Rx的主要接口深入理解的相关资料,需要的朋友可以参考下...2020-06-25
  • selenium 反爬虫之跳过淘宝滑块验证功能的实现代码

    这篇文章主要介绍了selenium 反爬虫之跳过淘宝滑块验证功能,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-08-27
  • Feign接口方法返回值设置方式

    这篇文章主要介绍了Feign接口方法返回值设置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-07-08
  • vue element table中自定义一些input的验证操作

    这篇文章主要介绍了vue element table中自定义一些input的验证操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-18
  • js canvas实现滑块验证

    这篇文章主要为大家详细介绍了js canvas实现滑块验证,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-03-14
  • vue设置全局访问接口API地址操作

    这篇文章主要介绍了vue设置全局访问接口API地址操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-14
  • 如何设计一个安全的API接口详解

    在日常开发中,总会接触到各种接口,前后端数据传输接口,第三方业务平台接口,下面这篇文章主要给大家介绍了关于如何设计一个安全的API接口的相关资料,需要的朋友可以参考下...2021-08-12
  • vue实现表单验证小功能

    这篇文章主要为大家详细介绍了vue实现表单验证小功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-29
  • 利用PS制作“签名”GIF小动画的例子

    本文章来为各位介绍一篇利用PS制作“签名”GIF小动画的例子,希望这个制作过程能够帮助到各位朋友,各位进入看看吧。 先给大家看下效果,有兴趣的童鞋&rarr;_&rarr;可以...2016-09-14
  • php怎么写api接口?php写api接口的实例代码

    php怎么写api接口?本文介绍了php写api接口的实例代码,有兴趣的同学可以参考一下。 http://localhost/openUser.php?act=get_user_list&type=json在这里openUser.php...2017-07-06
  • vue配置多代理服务接口地址操作

    这篇文章主要介绍了vue配置多代理服务接口地址操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-08