第三方接口对接
鉴权
记录一次和第三方接口对接的过程。
对接要求
对方的接口做了加密验证,需要将参数进行加密生成一个Signature签名。然后对方也会根据参数做一样的步骤来比对签名是否相等来判断参数是否被篡改或者判断身份是否一致。
对方提供了以下几个参数:
accessKey
: 和参数进行混合的keyaccessSecret
: 进行base64编码的时候的密码dateTime
: 密钥生成的时间,对方文档会标注根据该时间来判断接口的有效时间。比如5分钟内该参数是有效的,超过5分钟对方就认为这个请求已经过期了。randomNumbers
: 随机数password
: DES加密的密码
加密的类型:
明文参数:
- 手机号码 : 需要通过DES进行加密,加密的密码为上面提供的password。
密文参数:
-
首先拿到明文参数
-
参数的顺序必须一致:例如一段json字符串数据,里面的key必须按照a-z不区分大小写的顺序进行排列。
-
除了业务参数,还有通用参数:
accessKey
、dateTime
、randomNumbers
等等加入到参数字符串中。 -
所有的key对应的value必须要经过URLEncoder进行编码,避免出现中文乱码的情况。
-
将所有参数通过字符串拼接成一个整的字符串,类似于URL中GET请求参数的样子。然后将得到的这个参数值进行HMACSHA1加密,加密的密钥为accessSecret。
-
最后通过Base64生成密钥。
-
将这个密钥加入到请求的header头中。
-
header头也需要带上通用参数。
以上加密的方式主要是为了保证,参数不能被篡改,调用方的身份验证。两边加密和解密的步骤是一致的。否则就会鉴权失败。
另外简单描述一下各个加密的用处:
HMACSHA1 : 是从 SHA1 哈希函数构造的一种键控哈希算法,被用作 HMAC(基于哈希的消息验证代码)。 此 HMAC 进程将密钥与消息数据混合,使用哈希函数对混合结果进行哈希计算,将所得哈希值与该密钥混合,然后再次应用哈希函数。 输出的哈希值长度为 160 位。
在发送方和接收方共享机密密钥的前提下,HMAC 可用于确定通过不安全信道发送的消息是否已被篡改。 发送方计算原始数据的哈希值,并将原始数据和哈希值放在一个消息中同时传送。 接收方重新计算所接收消息的哈希值,并检查计算所得的 HMAC 是否与传送的 HMAC 匹配。
Base64 : 是一种任意二进制到文本字符串的编码方法,常用于在URL、Cookie、网页中传输少量二进制数据。
DES加密 : 双方约定一致的key进行加密,生成64位的明码形式进行传输,各方可以通过key进行解密
关键代码展示:
HMACSHA1 :
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class HMACSHA1 {
private static final String MAC_NAME = "HmacSHA1";
private static final String ENCODING = "UTF-8";
/*
* 展示了一个生成指定算法密钥的过程 初始化HMAC密钥
* @return
* @throws Exception
*
public static String initMacKey() throws Exception {
//得到一个 指定算法密钥的密钥生成器
KeyGenerator KeyGenerator keyGenerator =KeyGenerator.getInstance(MAC_NAME);
//生成一个密钥
SecretKey secretKey =keyGenerator.generateKey();
return null;
}
*/
/**
* 使用 HMAC-SHA1 签名方法对对encryptText进行签名
* @param encryptText 被签名的字符串
* @param encryptKey 密钥
* @return
* @throws Exception
*/
public static byte[] HmacSHA1Encrypt(String encryptText, String encryptKey) throws Exception
{
byte[] data=encryptKey.getBytes(ENCODING);
//根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
SecretKey secretKey = new SecretKeySpec(data, MAC_NAME);
//生成一个指定 Mac 算法 的 Mac 对象
Mac mac = Mac.getInstance(MAC_NAME);
//用给定密钥初始化 Mac 对象
mac.init(secretKey);
byte[] text = encryptText.getBytes(ENCODING);
//完成 Mac 操作
return mac.doFinal(text);
}
}
DESUtils:
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.SecureRandom;
public class DESUtils {
/**
* @param data
* @return
* @throws Exception
* @Method: encrypt
* @Description: 加密数据
* @date 2016年7月26日
*/
public static String encrypt(String data, String password) {
//对string进行BASE64Encoder转换
byte[] bt = encryptByKey