今天遇到了一个问题,其他部门在调用我们开放平台接口时,总出现签名错误,
(客户端和服务器使用的是同一个签名算法JAR包)
问题说明:
1, 在项目部署到tomcat上调用接口时,会出现签名错误。
2, 如果直接在java的main函数调用接口,则不会出现。
注:1,2的请求参数都完全相同,并使用同一个签名算法
签名算法的流程如下:
1、将所有POST参数(key-value)按照key升序将value拼接在一起;
2、将1的结果的首尾加上appSecret值,例如:appSecretvalue1value2appSecret
3、将2的结果进行MD5大写加密。
在2中得到的结果是一样的,但在第3步时出现了不同
MD5算法怎么会不同呢?JAVA里面MD5算法不是统一的吗?
仔细查看了源码,发现是在调用s.getBytes()方法时出现了不同,代码如下:
getMD5String(s.getBytes());
s为需要MD5的字符串
在网上查了下普遍说s.getBytes()方法是得到一个操作系统默认的编码格式的字节数组,在不同的OS系统下,返回的结果不一样。
既然这样,那么我在tomcat中和JAVA的main函数中调用s.getBytes()应该获取的应该改是一样的?我都是在本机运行的,操作系统都是window7,默认编码都是GBK,Why???
查看了s.getBytes()方法源码可以看到,默认是使用:
Charset.defaultCharset()
查看官方JDK对其解释:
public static Charset defaultCharset()
Returns the default charset of this Java virtual machine.
The default charset is determined during virtual-machine startup and typically depends upon the locale and charset of the underlying operating system.
获取JVM默认的的编码格式,其默认编码格式又依赖于底层操作系统的编码格式。
可以猜测如果设置了JVM的编码格式,则使用此编码,如果没有设置则使用操作系统的默认编码格式,那又是在哪设置的JVM的编码格式呢?
Debug一下:
1, 通过java的main函数运行,在debug模式下:
可以看到在运行时,指定了默认编码为UTF-8
2, 通过tomcat启动运行,在debug模式下
可以看到,指定的编码格式为GBK
更改文件的编码格式为ISO-8859-1,在进行测试
1, 使用java的main函数直接运行
可以看到编码格式变为ISO-8859-1了
2, 使用tomcat运行项目:
可以看到其编码格式还是GBK的
可以得出结论:
1, 在eclipse中使用java的main函数运行程序,其JVM的默认编码为文件的默认编码
2, 在tomcat是运行项目,JVM不是使用文件的默认编码,若tomcat未指定编码,则使用系统的默认编码
那么我们要统一编码,该怎么做呢?可以在s.getBytes()方法中加入编码格式,如:s.getBytes(“UTF-8”),统一使用UTF-8的编码格式,我们来试试
1, 使用java的main函数直接运行,得到的结果:
file.encode: ISO-8859-1
sign: 2B6C5716E9A7D270DA299DCA1A737FF0
2, 使用tomcat运行项目,得到的结果:
file.encode: GBK
sign: 2B6C5716E9A7D270DA299DCA1A737FF0
其他方法:
(1) 另外,tomcat也可以指定JVM的编码格式,在catalina.bat或catalina.sh中修改
set “JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%”
为:
set “JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG% -Dfile.encoding=UTF-8”
(2) 修改系统的默认编码,目前服务器一般使用linux服务器,将服务器的编码设置为UTF-8