1. 签名算法说明
对于每一次HTTPS协议请求,我们会根据访问中的签名信息验证访问请求者身份。具体由使用appId和appSecret对称加密验证实现。
appSecret相当于用户密码,appId用于调用API,而用户密码用于登录CMP控制台 。其中appId是访问者身份,appSecret是加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密谨防泄露。
2. 签名信息发送
签名信息通过HTTP头(x-ycs-security-authorization)随HTTP请求发送
3. 签名信息格式
[Authorization:] [SIGN METHOD] [Credential=xxx],[SignedHeaders=xxx;xxx;xxx],[Signature=xxx]
签名信息分为5段,上面以[]分割,其中[]只是为了用以区别分割每段,前面两段以英文空格分割后面三段以英文的,字符分割
[Authorization:]
为固定格式字符串,注意大小写及使用英文:字符
[SIGN METHOD]
为签名算法的名称,目前只支持HMAC-SHA1,对应的算法名称为YCS1-HMAC-SHA1
[Credential=xxx]
=后面的xxx替换为用户的appId
[SignedHeaders=xxx;xxx;xxx]
=后面的为在签名签名算法中使用到的摘要信息在HTTP头中的名称,以英文;字符分割
[Signature=xxx]
=后面的xxx替换为签名字符串
4. 签名信息生成算法
签名算法是通过请求的HTTP头中设置的参数和请求的包体生成签名的摘要,然后用appSecret作为秘钥对签名摘要进行签名算法加密的过程。签名字符串生成过程可以分为以下三个步骤:
4.1. 步骤 1. 确定摘要内容
生成签名字符串,首先需要确定签名的摘要内容,即确定通过哪些信息生成签名摘要。
摘要字段可以自定义,我们建议至少包含公共请求头中的x-ycs-requestid,x-ycs-timestamp字段。
摘要内容必须包含HTTP请求包体的内容,HTTP请求包体的内容作为requestBody参数参与签名
示例:
String signedHeaders="x-ycs-requestid;x-ycs-timestamp;x-my-header";
4.2. 步骤 2. 构造签名摘要
将所有签名内容名称按照字母序排序后,通过&连接key=value字符串组成签名摘要
示例:
Map<String, String> signParams = new HashMap<>();
String requestId = UUID.randomUUID().toString();
String timestamp = DateUtils.getISO8601Time(null);
String requestBody = "{\"name\":\"新建项目\",\"color\":\"project-color-1\"}";
signParams.put("x-ycs-requestid", requestId);
signParams.put("x-ycs-timestamp", timestamp);
signParams.put("x-my-header", "just add something");
signParams.put("requestBody", requestBody);
List<String> keys = new ArrayList<>(signParams.keySet());
Collections.sort(keys);
StringBuilder sb = new StringBuilder();
for(String key : keys) {
sb.append("&").append(key).append("=").append(signParams.get(key));
}
String signSummary = sb.toString().substring(1);
4.3. 步骤 3. 构造签名字符串
用appSecret作为秘钥加密签名摘要,生成签名字符串
示例:
String signature = Signers.getSigner(HmacSHA1Signer.NAME).sign(signSummary, appSecret);
String authorization = "Authorization: " + HmacSHA1Signer.NAME + " Credential=" + appId +",SignedHeaders="+signedHeaders+",Signature=" + signature;
5. 创建项目JAVA代码完整示例
Map<String, String> signParams = new HashMap<>();
String signedHeaders="x-ycs-requestid;x-ycs-timestamp;x-my-header";
String appId = "10736709-63ca-401f-92ea-2e532045b8f0";
String appSecret = "e5dd6045-d369-11e8-88a8-fa163ebc68d3";
String requestId = UUID.randomUUID().toString();
String timestamp = DateUtils.getISO8601Time(null);
String requestBody = "{\"name\":\"新建项目\",\"color\":\"project-color-1\"}";
signParams.put("x-ycs-requestid", requestId);
signParams.put("x-ycs-timestamp", timestamp);
signParams.put("x-my-header", "just add something");
signParams.put("requestBody", requestBody);
List<String> keys = new ArrayList<>(signParams.keySet());
Collections.sort(keys);
StringBuilder sb = new StringBuilder();
for(String key : keys) {
sb.append("&").append(key).append("=").append(signParams.get(key));
}
String signSummary = sb.toString().substring(1);
String signature = Signers.getSigner(HmacSHA1Signer.NAME).sign(signSummary, appSecret);
String authorization = "Authorization: " + HmacSHA1Signer.NAME+" Credential=" + appId +",SignedHeaders="+signedHeaders+",Signature=" + signature;
HttpClient client = HttpClientBuilder.create().disableAuthCaching().disableRedirectHandling().disableAutomaticRetries().disableCookieManagement().build();
HttpPost post = new HttpPost("https://api.yovole.com/v1/project/createProject");
post.setHeader("x-ycs-requestid", requestId);
post.setHeader("x-ycs-timestamp", timestamp);
post.setHeader("x-my-header", signParams.get("x-my-header"));
post.setHeader("x-ycs-security-authorization", authorization);
post.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8));
String response = client.execute(post, new BasicResponseHandler());