签名生成方法
- 所有请求参数(不包括signature不包括signature,redirecturl), 加入平台密钥secret=xxx(从兔展开放平台获取找给客户开通平台的兔展运营同学 或者 营销平台租户端系统的开发者中心), 根据参数名称进行字典递增排序(按照第一个字符的键值ASCII码递增排序, 如果遇到相同字符则按照第二个字符的键值ASCII码递增排序, 以此类推)
- 将排序后的参数与其对应值, 组合成"参数=参数值"的形式, 然后用'&'字符连接起来, 作为待签名字符串
将待签名字符串使用SHA1算法处理, 结果作为signature(签名)的值
注意事项
secret只在待签名字符串中使用,请求接口时,请勿带上secret参数。signature有效期60秒,超过60秒的请求会提示 signature已过期secret只在待签名字符串中使用,请求接口时,请勿带上secret参数
以下提供了3种实现方式请参考:JavaScript、Java、Postman(GET, POST有区别)
代码参考
以JavaScript代码为例
代码块 | ||||||
---|---|---|---|---|---|---|
| ||||||
<script src="https://cdn.bootcss.com/crypto-js/3.1.9-1/crypto-js.min.js"></script> <script> const iframe = document.querySelector('#test-iframe'); function getUnionLoginParams() { const nonce = 'fb4706'; const opfid = '572115641423875';//开发者中心获取 const uid = '18576626619'; const secret = '92cba47a143a0c22ee7';//开发者中心获取 const timestamp = Date.now().toString(); const params = { opfid, secret, uid, nonce, timestamp }; const query = Object.keys(params) .sort( (key1, key2) => key1.charCodeAt(0) - key2.charCodeAt(0) ) .reduce((str, key) => (str += `${key}=${params[key]}&`), '') .slice(0, -1); const signature = CryptoJS.SHA1(query).toString(CryptoJS.enc.Hex); return { nonce, opfid, uid, timestamp, signature }; } const params = getUnionLoginParams(); let loginUrl = 'https://open.rabbitpre.com/union-login.html'; loginUrl += `?nonce=${params.nonce}`; loginUrl += `&opfid=${params.opfid}`; loginUrl += `&uid=${params.uid}`; loginUrl += `×tamp=${params.timestamp}`; loginUrl += `&signature=${params.signature}`; loginUrl += `&redirecturl=${encodeURIComponent('https://www.rabbitpre.com/template/multipage.html')}`; iframe.setAttribute('src', loginUrl); </script> |
...
代码块 | ||||
---|---|---|---|---|
| ||||
SortedMap<String, String> map = new TreeMap<String, String>(); map.put("opfid", opfid); map.put("nonce", nonce); map.put("timestamp", timestamp); map.put("secret", secret); map.put("uid", uid); String signature = SHA1Util.createSHA1Sign(map); System.err.println("--signature生成signature-->>" + signature); companyId 打印信息: --拼接计算signature的入参-->>companyId=1&nonce=123456&opfid=65499870709224111111&secret=2222222222222222×tamp=1625194549051&uid=1000010001 --signature→>c1e0401e25926f3d42de2f03fc989eec4f15b01d--生成signature-->>c1e0401e25926f3d42de2f03fc989eec4f15b01d |
SHA1Util参考代码
代码块 | ||||
---|---|---|---|---|
| ||||
package com.base.utils;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.Iterator;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SHA1Util {
protected static final Logger logger = LoggerFactory.getLogger(SHA1Util.class);
public SHA1Util() {
}
public static String getTimeStamp() {
return String.valueOf(System.currentTimeMillis() / 1000L);
}
public static String createSHA1Sign(SortedMap<String, String> signParams) {
StringBuffer sb = new StringBuffer();
Set es = signParams.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Entry params = (Entry)it.next();
String k = (String)params.getKey();
String v = (String)params.getValue();
sb.append(k + "=" + v + "&");
}
String params1 = sb.substring(0, sb.lastIndexOf("&"));
System.out.println("--拼接计算signature的入参-->>"+params1);
return getSha1(params1);
}
public static String getSha1(String str) {
if(str != null && str.length() != 0) {
char[] hexDigits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
try {
MessageDigest e = MessageDigest.getInstance("SHA1");
e.update(str.getBytes("UTF-8"));
byte[] md = e.digest();
int j = md.length;
char[] buf = new char[j * 2];
int k = 0;
for(int i = 0; i < j; ++i) {
byte byte0 = md[i];
buf[k++] = hexDigits[byte0 >>> 4 & 15];
buf[k++] = hexDigits[byte0 & 15];
}
return new String(buf);
} catch (Exception var9) {
logger.error("--计算signature--getSha1 error", var9);
throw new RuntimeException(var9.getMessage(), var9);
}
} else {
return null;
}
}
}
|
后续技术对接,首先执行联合登录接口。开放平台目前只支持HTML联合登录的方式(即浏览器访问如下示例)
下面示例是test环境的域名(生产域名: https://open.rabbitpre.com):后续技术对接,首先执行联合登录接口。开放平台目前只支持HTML联合登录的方式(即浏览器访问如下示例)
https://testopen.rabbitpre.com/union-login.html?nonce=123456&opfid=65499870709224111111&uid=uidjj×tamp=1625194549051&signature=c1e0401e25926f3d42de2f03fc989eec4f15b01d&redirecturl=https://home.rabbitpre.com
签名帮助(sha1算法)(使用postman调试接口)
第一步:填写参数
第二步:填写脚本
脚本:
代码块 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
/** * 通过request.data获取body的内容,这个是postman内置变量 * 常用内置参数如下: * request 获取请求的参数,包括头和请求体 * responseHeaders 返回值的header * responseBody 返回值的body * responseCode 返回值的http code */ var params = pm.request.url.query.members; // console.log("params:",paramsvar map = new Map(); map.set("secret","89908acc57d64110b0b805977244d5c6") var maptimestamp = Date.parse(new MapDate()); map.set("timestamp",timestamp) for (var i=0; i<params.length; i++) { // console.log(params[i]) if(params[i].key=="signature"){ continue } if(params[i].key=="timestamp"){ // let time2 = new Date().getTime(); console.log("------------------") // map.set(params[i].key,time2) continue } map.set(params[i].key,params[i].value) } console.log(map) var arrayObj=Array.from(map); arrayObj.sort(function(a,b){return a[0].localeCompare(b[0])}) //字段重新组装拼接 var tmp=''; for(var i=0;i<arrayObj.length;i++){ tmp += arrayObj[i][0]+"="+arrayObj[i][1]+"&"; } tmp = tmp.substring(0,tmp.lastIndexOf("&")) console.log(arrayObj) // //body中参数放入数组"tmp ---->" + tmp); //生成签名串:这里使用SHA1算法并使用十六进制编码 //CryptoJS-为JavaScript提供了各种各样的加密算法 //作者:CryptoJS<>(https://code.google.com/p/crypto-js/) // var list = [params.subsystemId,params.clientId,params.account,params.timestamp]; // signHmacSHA1=CryptoJS.SHA1(tmp).toString(CryptoJS.enc.Hex).toUpperCase(); var signHmacSHA1=CryptoJS.SHA1(tmp).toString(CryptoJS.enc.Hex); console.log("listsign ---->" + listsignHmacSHA1); // /放入环境变量 //pm.environment.set("sha1msg",signHmacSHA1) postman.setGlobalVariable("signature", signHmacSHA1); postman.setGlobalVariable("timestamp", timestamp); |
第三步:修改脚本,如下secret,填写正确的开放平台密钥
POST请求方式签名
第一步:填写参数
第二步:填写脚本和密钥
代码块 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
var params = request.data let parmsJson = JSON.parse(params) var map = new Map(); map.set("secret","0fdb9fc1c0ca423c9af1f87baaf711d3") var timestamp = Date.parse(new Date()); map.set("timestamp",timestamp) for(var key in parmsJson){ if(key=="signature"){ continue } if(key=="timestamp"){ continue } map.set(key,parmsJson[key]) } console.log(map) var arrayObj=Array.from(map); arrayObj.sort(function(a,b){return a[0].localeCompare(b[0])})/ 字段排序:这里建议使用默认的排序,优先比较字符的第一个,相同则比对第二个... // //list.sort(function(a, b){ // //return b-a; //数字的排序 // // return b.localeCompare(a); //字符串排序 // //}); // console.log("list ---->" + list); //字段重新组装拼接 var tmp=''; for(var i=0;i<arrayObj.length;i++){ var value = arrayObj[i][1] if(value instanceof Object){ value = JSON.stringify(arrayObj[i][1]) } tmp += arrayObj[i][0]+"="+arrayObj[i][1]value+"&"; } tmp = tmp.substring(0,tmp.lastIndexOf("&")) console.log("tmp ---->" + tmp); //生成签名串:这里使用SHA1算法并使用十六进制编码 //CryptoJS-为JavaScript提供了各种各样的加密算法 //作者:CryptoJS<>(https://code.google.com/p/crypto-js/) // var signHmacSHA1=CryptoJS.SHA1(tmp).toString(CryptoJS.enc.Hex).toUpperCase(); var signHmacSHA1=CryptoJS.SHA1(tmp).toString(CryptoJS.enc.Hex); console.log("sign ---->" + signHmacSHA1); //放入环境变量 //pm.environment.set("sha1msg",signHmacSHA1) postman.setGlobalVariable("signature", signHmacSHA1); postman.setGlobalVariable("timestamp", timestamp); |