web签名验证程序【跨服务器、中文字符签名方法】-php为例

做电子商务网站,少不了接入支付。做开发同学知道,支付需要调试很多项,比较耗费时间,又有些挑战性的就是它的支付签名验证了。 首先,我们看一下接口数字签名是怎么回事。

 

一、接口数字签名

甲方是:服务提供商,开方一个接口。getuserinfo.php ,接收:coid(乙方的标示) username(用户名) 调用接口,返回用户信息,这里只以二个字段说明。

 

乙方是:服务接口调用商,通过应用程序,调用甲方getuserinfo.php 接口。

 

问题:甲方的接口是在互联网上面,对于所有公众都是可以访问的。但是他需要控制,访问接口用户是它授权的用户。

解决方案是:甲方加入一个签名字段,乙方调用时候必须将该字段传入。甲乙双方,通过一个私自定义的字串(私钥),加入到签名中。以上字段将变成:

 

getuserinfo.php接口接收参数
参数 说明
coid 字符型,乙方的编号
username 字符串,需要查询用户信息
sign

数字签名,它的值是:

md5(coid+username+key)

  甲乙双方私钥key是:asdf@#%#%#%

 

这种,就是互联网上面,常见的接口的数字签名 实例。 coid,username任意改变,sign结果就会改变。甲方通过验证这个sign就能判断。数据是否是乙方传入的。因为:私钥key 是除了他们知道,不会让第3方获得。 这样就保证了接口安全。

二、md5签名中问题(中文验证不通过)

问题:

当coid,username都为字符串时候,双方签名都调试通过,后来发现username 为中文了,签名不能通过。

这个问题是怎么样产生的呢?可能有的朋友,会跟对方进行操作,都用某个中文进行md5运算,发现得到结果不一致?

如是得出结果是:我们两个md5函数不标准,或者是不同语言下,md5函数计算结果不一样。 呵呵,这个结论得出后,就认为签名不能通过了。 于是乎,有个同学,在自己电脑里面安装几个程序,进行md5中文签名,发现得到结果一样。

分析,继续思考……

结果:发现这几个程序所使用编码都一致,所以中文签名结果一样的。

终于发现问题了:签名不一致是由于程序的字符编码不一致原因。 如果大家看了:web 程序乱码深入分析【基础原理篇】--php为例 可能就知道该怎么做了。 这里我先说明下签名函数md5是怎么样处理的。

md5函数:以传入字节码为内容进行签名验证。因此,需要签名结果一致,只需要传入参数字节码是相同的,那么md5签名结果就相同。

 

相同汉字不同字节码:

以下以汉字“中”为例:

gb2312 字节码是:D6D0

utf-8    字节码是:E4B8AD

在2个程序里面,默认字符集不同,看是都是相同中文,md5结果自然就不同了。

三、web通讯中签名怎么样做?

还是以上面为例:

甲方:程序是utf-8编码

乙方:程序是gb2312编码

image

通过流程我们很轻易知道,做sign验证时候,甲方在获得变量时候就进行,如:

乙方代码:(test.php 保存时保存为:gb2312编码或ansi或gbk)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
header( "Content-type:text/html;charset=gb2312" );
$key = "asdf@#%#%#%" ;
$sign =md5( "chengmo" . "中" . $key );
?>
<html xmlns= "http://www.w3.org/1999/xhtml" >
<head>
<title>测试</title>
<meta http-equiv= "Content-Type"  content= "text/html; charset=gb2312"  />
</head>
<body>
<form action= "test2.php" >
合作:<input name= "coid"  value= "chengmo"  readonly/>
用户名:<input name= "username"  value= "中"  readonly/>
sign:<input name= "sign"  value= "<? echo $sign?>" />
<input type= "submit" />
</form>
</body>
</html>

甲方代码:(test2.php保存时候选择:utf-8)

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
header( "Content-type:text/html;charset=utf-8" );
 
$key = "asdf@#%#%#%" ;
$coid =isset( $_REQUEST [ 'coid' ])?trim( $_REQUEST [ 'coid' ]): "" ;
$username =isset( $_REQUEST [ 'username' ])?trim( $_REQUEST [ 'username' ]): "" ;
$sign =isset( $_REQUEST [ 'sign' ])?trim( $_REQUEST [ 'sign' ]): "" ;
 
echo  "_sign=" ,md5( $coid . $username . $key ), "</br>" ;
echo  "coid=" , $coid , "</br>" ;
echo  "username=" ,iconv( "gb2312" , "utf-8" , $username ), "</br>" ;
echo  "sign=" , $sign , "</br>" ;
?>
1
截图显示:
1
<a href= "http://images.cnblogs.com/cnblogs_com/chengmo/WindowsLiveWriter/web_1055B/image_6.png" ><img style= "display: inline; border: 0px;"  title= "image"  src= "http://images.cnblogs.com/cnblogs_com/chengmo/WindowsLiveWriter/web_1055B/image_thumb_2.png"  border= "0"  alt= "image"  width= "578"  height= "269" ></a>
1
这里只是以一个简单程序做例子,说明跨字符集程序中,签名需要怎么样处理。我们总结一下:
1
<span style= "color: #800080;" ><strong>无论什么样字符集,获得对方原始值后,直接先做签名验证,再做转码。这个规律所有语言都适用!!!</strong></span>
1
  
1
  
1
<span style= "color: #808000;" >疑问:看了<a href= "http://www.cnblogs.com/chengmo/archive/2010/10/18/1854714.html" >web 程序乱码深入分析【基础原理篇】--php为例</a> 可能大家知道的,无论什么应用程序,是不能准确通过字节流判断出它的编码的。 那么我们做接口开发时候,可以仿照下:http协议,在接口里面加入,字符集属性字段。清楚告诉它,我返回将时什么字符。现在,各大支付网关,都有类似扩展字段,让调用接口方,告诉它传入字符编码是那种类型。 你们可以查阅下它们接口看看。</span>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值