客户端和服务器端包含中文参数值导致签名不一致的问题

在本地开发,Intellij Idea运行的是嵌入式tomcat,测试时签名没有任何问题。
发布到阿里云服务器上测试时,发现客户端和服务器端的签名不一致,总是导致认证失败。进一步排查,发现是参数值包含中文时才导致签名不一致。
当时用的是ios客户端,开始怀疑是AFNetworking框架处理中文参数的问题,后来用web前端调用接口,依然存在问题。所以排查不是客户端处理中文字符的问题。
于是判断是不是tomcat8+springboot的问题,参考以下文章的处理,问题依然存在:
springboot全局字符编码设置(解决乱码问题)
Spring boot http编码配置(CharacterEncodingFilter)
tomcat7和tomcat8中文乱码问题

也排除中文乱码的问题,因为其实tomcat8和springBoot默认都是采取UTF-8编码。

最后仔细看ios端签名的算法:

+ (NSString *)MD5String:(NSString *)str
{
    const char* inString = [str UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    NSMutableString *outStrg = [NSMutableString string];
    
    CC_MD5(inString, (CC_LONG)strlen(inString), result);
    
    unsigned int i;
    for (i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        [outStrg appendFormat:@"%02x", result[i]];
    }
    return [outStrg copy];
}

const char* inString = [str UTF8String];

这一行将字符串转换成utf-8再md5。

再看看java服务器端的md5算法:

public static String md5(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes());
            byte[] after = md.digest();
            StringBuffer sb = new StringBuffer();

            for(int i = 0; i < after.length; ++i) {
                sb.append(Integer.toHexString((after[i] & 240) >> 4));
                sb.append(Integer.toHexString((after[i] & 15) >> 0));
            }

            return sb.toString();
        } catch (NoSuchAlgorithmException var5) {
            throw new RuntimeException(var5);
        }
    }

md.update(str.getBytes());

str.getBytes()在本地开发环境默认获取的是UTF-8编码的字节,所以开发环境没有出现问题。
但部署到阿里云服务器后,获取的就不是UTF-8编码的字节了。
所以必须指定编码为UTF-8:

md.update(str.getBytes("utf-8"));

签名不一致的问题就解决了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容