Fork me on GitHub

AKSK安全认证

蓝卓开发者社区

APP集成 ∣ 深度集成方案

supOS SDK for Java 开发指南

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
String apibaseURL = System.getenv("SUPOS_SUPOS_ADDRESS");
//封装消息体
String body = "{\n" +
"\t\"sender\": \"admin\",\n" +
"\t\"source\": \"system\",\n" +
"\t\"type\":\"stationLetter\",\n" +
"\t\"receivers\": [\"xwj\"],\n" +
"\t\"content\":{\n" +
"\t\t\"title\":\"aaaaa\",\n" +
"\t\t\"text\":\"aaa\"\n" +
"\t}\n" +
"}";
//调用openapi签名工具类发送请求
Map<String, String> headMap = new HashMap<String, String>(){{
put("X-MC-Date","...");
put("X-MC-Type","...");
}};
String response = SignUtil.doHttpMethod(apiBaseURL,"/api/openapi/notification/v1/message", HttpMethod.POST, JSON.parseObject(body), headMap);

SignUtil 签名的工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

import cn.hutool.json.JSONObject;
import com.bluetron.eco.sdk.dto.common.SuposConfig;
import org.springframework.http.HttpMethod;
import com.google.common.net.HttpHeaders;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.nio.charset.StandardCharsets;
import java.util.*;

@Slf4j
public class SignUtil {

/**
* 通过AK/SK签名 发送HTTP请求调用open api接口
* @param apiPath api的请求路径 如:/openapi/users/v1?page=1&per_page=2
* @param method HttpMethod
* @param jsonBody 当method是post put等请求时,所携带的body
* @param headMap 签名需要用到的头
* @return
* @throws Exception
*/
public static String doHttpMethod(String apiPath, HttpMethod method, JSONObject jsonBody, Map<String, String> headMap) throws Exception {
log.info(">>>>>>>>>>>>> AK/SK 请求, apiPath: {} , method: {} ,jsonBody: {}, headMap: {}<<<<<<<<<<<<<<<<", apiPath, method, jsonBody, headMap);
SignRequest request = new SignRequest();
request.setSignUrl(SuposConfig.getSuposApiAddress(), apiPath);
request.setAppId(SuposConfig.getAppId());
request.setAppSecret(SuposConfig.getSecretKey());
request.setHttpMethod(method);
request.addHeader(HttpHeaders.CONTENT_TYPE, "application/json");
if (null != jsonBody) {
request.setBody(jsonBody.toString());
}
HttpRequestBase requestBase = createSignatureRequest(request, headMap);
CloseableHttpClient client = HttpClients.custom().build();

HttpResponse response = client.execute(requestBase);
int statusCode = response.getStatusLine().getStatusCode();
HttpEntity resEntity = response.getEntity();
String result = null;
if (resEntity != null) {
result = EntityUtils.toString(resEntity, "UTF-8");
}
log.info(">>>>>>>>>>>>> AK/SK 响应状态码: {} , 响应内容: {} <<<<<<<<<<<<<<<<", statusCode, result);
return result;
}

/**
* 创建一个具有AKSK签名的HTTP CLIENT请求
* request 加签参数
*/
private static HttpRequestBase createSignatureRequest(SignRequest request, Map<String, String> headMap) {
HttpRequestBase httpRequest;
StringEntity entity;
HttpMethod httpMethod = request.getHttpMethod();
String content = request.getBody();
String url = request.getSignUrl();
switch (httpMethod) {
case POST:
HttpPost postMethod = new HttpPost(url);
if (StringUtils.isNotEmpty(content)) {
entity = new StringEntity(content, StandardCharsets.UTF_8);
postMethod.setEntity(entity);
}
httpRequest = postMethod;
break;
case PUT:
HttpPut putMethod = new HttpPut(url);
if (StringUtils.isNotEmpty(content)) {
entity = new StringEntity(content, StandardCharsets.UTF_8);
putMethod.setEntity(entity);
}
httpRequest = putMethod;
break;
case PATCH:
HttpPatch patchMethod = new HttpPatch(url);
if (StringUtils.isNotEmpty(content)) {
entity = new StringEntity(content, StandardCharsets.UTF_8);
patchMethod.setEntity(entity);
}
httpRequest = patchMethod;
break;
case GET:
httpRequest = new HttpGet(url);
break;
case DELETE:
httpRequest = new HttpDelete(url);
break;
case OPTIONS:
httpRequest = new HttpOptions(url);
break;
default:
if (httpMethod != HttpMethod.HEAD) {
throw new RuntimeException("Unknown HTTP method name: " + httpMethod);
}
httpRequest = new HttpHead(url);
break;
}
//获取签名头
Map<String, String> headers = getSignatureHeader(request, headMap);
if (MapUtils.isNotEmpty(headMap)) {
headers.putAll(headMap);
}
Iterator<String> iterator = headers.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
httpRequest.addHeader(key, headers.get(key));
}
return httpRequest;
}

//获取AK/SK加签后的签名头
//request 加签参数
public static Map<String, String> getSignatureHeader(SignRequest request, Map<String, String> headMap) {
Map<String, String> headers = request.getHeaders();
StringBuffer sb = new StringBuffer();
sb.append(request.getHttpMethod().toString()).append("\n")
.append(request.getSignUrl()).append("\n")
.append(headers.get(HttpHeaders.CONTENT_TYPE)).append("\n");
//CanonicalQueryString
if (StringUtils.isNotEmpty(request.getQueryString())) {
sb.append(request.getQueryString().trim());
}
sb.append("\n").append(getCanonicalCustomHeaders(headMap).toString().trim());
log.info(">>>>>>>>>>>>> AK/SK 签名源内容:\n{} \n<<<<<<<<<<<<<<<<", sb);

log.info("appSecret: {}", request.getAppSecret());
HmacUtils hmacSha256 = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, request.getAppSecret());
String signature = hmacSha256.hmacHex(sb.toString());
String finalSignature = "Sign " + request.getAppId() + "-" + signature;
headers.put("Authorization", finalSignature);
log.info(">>>>>>>>>>>>> AK/SK 签名结果:Authorization : {} <<<<<<<<<<<<<<<<", finalSignature);
return headers;
}

//自定义的请求头
private static String getCanonicalCustomHeaders(Map<String, String> headMap) {
return "x-mc-date:" + headMap.get("X-MC-Date") + ";x-mc-type:" + headMap.get("X-MC-Type");
}


}
-------------The End-------------