简单身份认证
客户端程序将AppCode和AppKey拼接后放到Request Header中,或者放到Request的Query参数中,从而进行身份认证。
参数名称 | 说明 | 示例值 |
Date | GMT格式的日期格式 | Fri, 18 Jun 2021 07:14:23 GMT |
Authorization | 调用方的<AppCode><空格><AppKey> | productcode 3FQoSpxUbCgz5bCss |
说明
简单身份认证模式下无需额外计算,直接使用上文获取的应用相关信息便可发起请求。
加密身份认证
客户端程序需要使用AppKey和AppSecret,对一系列需要签名所需要的信息进行哈希运算,得到签名结果(一串字符串)。在调用API时,Request Header增加签名结果和密钥的内容,从而进行身份认证。
加密计算过程较为复杂,建议您优先使用产品提供的SDK及代码示例开始调用。
参数名称 | 说明 | 示例值 |
Date | GMT格式的日期格式 | Fri, 18 Jun 2021 07:14:23 GMT |
signature | 计算得到签名 | productcode 3FQoSpxUbCgz5bCss:BwLDKVZxb6Ig7T6PdEibkWfkftFQ= |
计算说明
1)Content计算:
# GET请求
${method}\n${path}\n${date}
# 非GET请求
${method}\n${path}\n${date}\n${bodyMd5}
2)SignStr计算:
对步骤1)得到的Content内容,以AppSecret为密钥做HmacSHA1加密后,对密文做base64编码输出
3)signature计算:
signature = AppCode<空格>AppKey:SignStr
说明
path中如果包含特殊字符需要做Encode。
使用示例
1. Java应用-SDK调用(推荐)
Dbus已经将加密身份认证模式所需的签名的计算方法封装在SDK中,以供调用方的Java应用集成,引入SDK后可以直接通过SDK中的方法发起调用请求,无需再手动计算认证签名,方便快捷。
1)在应用中通过Maven添加如下依赖:
<dependency>
<groupId>com.aliyun.dataq.service.dbus</groupId>
<artifactId>dbus-sdk</artifactId>
<version>1.0.3-SNAPSHOT</version>
</dependency>
2) 手动下载SDK后在本地引入依赖
下载链接:SDK下载
安装至本地仓库:
mvn install:install-file\
-DgroupId=com.aliyun.dataq.service.dbus\
-DartifactId=dbus-sdk\
-Dversion=1.0.3-SNAPSHOT\
-Dpackaging=jar\
-Dfile=${安装包所在的本机路径}/dbus-sdk-1.0.3-SNAPSHOT-jar-with-dependencies.jar
SDK调用示例代码:
public static void main(String[] args) {
//目标API的地址
String endpoint = "https://dataq.aliyuncs.com";
//目标API的路径
String path = "/yourworkspaceCode/yourAppCode/APIPath";
//已获得调用授权或者自有API创建时选择的应用Code、AppKey及AppSecret
String appCode = "yourAppCode";
String appKey = "yourAppKey";
String appSecret = "yourAppSecret";
DataQService.Builder builder = new DataQService.Builder();
builder.setPath(path);
builder.setAppKey(appKey);
builder.setAppSecret(appSecret);
builder.setModuleName(appCode);
//添加请求Header参数
Map<String, Object> headerMap = new HashMap<>();
headerMap.put("Accept", "application/json");
headerMap.put("Content-Type", "application/json");
headerMap.put("h1", "");
headerMap.put("h2", "");
builder.addHeader(headerMap);
//添加QueryParam参数
Map<String, Object> queryParam = new HashMap<>();
queryParam.put("p1", "");
queryParam.put("p2", "");
builder.addQueryParam(queryParam);
//添加RequestBody参数
Map<String, Object> map = new HashMap<>();
map.put("b1", "");
List<String> values = Arrays.asList("v1");
map.put("b2", values);
builder.setRequestBody(new JSONObject(map));
//文件上传
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create()
.addTextBody("k1","v1")
.addTextBody("k2","v2")
.addBinaryBody("file", new File("/demo/2602780.txt"), ContentType.APPLICATION_OCTET_STREAM, "2602780.txt");
builder.setMultipartEntityBuilder(multipartEntityBuilder);
//设置请求方法
DataQService dataQService = builder.setHttpMethod(HttpMethod.GET).build();
//初始化请求客户端
DaasClient client = new DaasClient(endpoint);
//发送请求
Object httpResponse = client.invoke(dataQService, 1000000, 30);
//返回结果
System.out.println(httpResponse);
}
b. Java应用-自行计算签名
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public abstract class SignUtils {
public static final String EMPTY_STRING_MD5;
private static FastDateFormat DATE_FORMAT;
static {
DATE_FORMAT = FastDateFormat
.getInstance("E, dd MMM yyyy HH:mm:ss z", TimeZone.getTimeZone("GMT"), Locale.UK);
try {
MessageDigest md = MessageDigest.getInstance("md5");
md.update("".getBytes("UTF-8"));
EMPTY_STRING_MD5 = Base64.encodeBase64String(md.digest());
} catch (Exception ex) {
throw new IllegalArgumentException(ex);
}
}
public static Date parseGmtDate(String date) throws ParseException {
return DATE_FORMAT.parse(date);
}
public static String formatGmtDate(Date date) {
return DATE_FORMAT.format(date);
}
public static String toMd5(InputStream stream) throws Exception {
return toMd5(stream, false);
}
public static String toMd5(InputStream stream, boolean parseEmptyStream) throws Exception {
try {
boolean nocontent = true;
MessageDigest md = MessageDigest.getInstance("md5");
int len = -1;
byte[] buf = new byte[1024];
while ((len = stream.read(buf)) != -1) {
nocontent = false;
md.update(buf, 0, len);
}
return nocontent ?
(parseEmptyStream ? EMPTY_STRING_MD5 : "") :
Base64.encodeBase64String(md.digest());
} finally {
stream.close();
}
}
public static String toMd5(byte[] content) throws Exception {
if (content == null || content.length == 0) {
return null;
}
return Base64.encodeBase64String(MessageDigest.getInstance("md5").digest(content));
}
public static String toMd5(String content) throws Exception {
return toMd5(content.getBytes("UTF-8"));
}
public static String toHmacSHA1(String data, String AppSecret) throws Exception {
String algorithm = "HmacSHA1";
SecretKeySpec signingKey = new SecretKeySpec(AppSecret.getBytes("UTF-8"), algorithm);
Mac mac = Mac.getInstance(algorithm);
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(data.getBytes("UTF-8"));
return Base64.encodeBase64String(rawHmac);
}
public static String sign4Base(String param, String salt) throws Exception {
if (StringUtils.isEmpty(param) || StringUtils.isEmpty(salt)) {
return null;
}
String query = URLDecoder.decode(param, "UTF-8");
String[] pStr = query.trim().split("&");
Arrays.sort(pStr);
StringBuilder buf = new StringBuilder(salt).append(':');
for (int i = 0; i < pStr.length; ++i) {
buf.append(pStr[i]);
buf.append("&");
}
buf.setCharAt(buf.length() - 1, ':');
buf.append(salt);
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] bytes = md.digest(buf.toString().getBytes("UTF-8"));
return Hex.encodeHexString(bytes).toLowerCase();
}
private static String signedString(String method, String url, String date, String contentMd5) {
HttpMethod hm = HttpMethod.valueOf(method.toUpperCase());
if (hm == null) {
throw new IllegalArgumentException("Unknow Http Method: " + method);
}
if (hm.needBody && contentMd5 == null) {
contentMd5 = "";
}
if (contentMd5 == null) {
StringBuilder buf = new StringBuilder(method.length() + url.length() + date.length());
return buf.append(method).append('\n').append(url).append('\n').append(date).toString();
}
StringBuilder buf = new StringBuilder(
method.length() + url.length() + date.length() + contentMd5.length());
return buf.append(method).append('\n').append(url).append('\n').append(date).append('\n')
.append(contentMd5).toString();
}
private static String doSign(String module, String appKey, String appSecret, String signedString)
throws Exception {
String signature = toHmacSHA1(signedString, appSecret);
StringBuilder buf = new StringBuilder(module.length() + accessId.length() + signature.length() + 2);
return buf.append(module).append(' ').append(appKey).append(':').append(signature).toString();
}
public static String originalSign4Dtboost(String appSecret, String method, String url, String gmtDate)
throws Exception {
return originalSign4Dtboost(appSecret, method, url, gmtDate, null);
}
public static String originalSign4Dtboost(String appSecret, String method, String url, String gmtDate,
String contentMd5) throws Exception {
String signedString = signedString(method, url, gmtDate, contentMd5);
return toHmacSHA1(signedString, appSecret);
}
public static String sign4Dtboost(String module, String appKey, String appSecret, String method,
String url, String gmtDate) throws Exception {
return sign4Dtboost(module, appKey, appSecret, method, url, gmtDate, null);
}
public static String sign4Dtboost(String module, String appKey, String appSecret, String method,
String url, String gmtDate, String contentMd5) throws Exception {
String signedString = signedString(method, url, gmtDate, contentMd5);
return doSign(module, appKey, appSecret, signedString);
}
public static String[] spliteSign4Dtboost(String signature) {
int moduleIndex = signature.indexOf(' ');
if ((moduleIndex < 1) || (moduleIndex + 3) == signature.length()) {
return null;
}
int accessIdIndex = signature.indexOf(':', moduleIndex);
if ((accessIdIndex < 2) || (accessIdIndex + 1) == signature.length()) {
return null;
}
return new String[] {signature.substring(0, moduleIndex),
signature.substring(moduleIndex + 1, accessIdIndex), signature.substring(accessIdIndex + 1)};
}
private static String signedString(String method, String accept, String gmtDate, String url,
String contentType, String contentMd5) {
if (accept == null) {
accept = "";
}
if (contentType == null) {
contentType = "";
}
if (contentMd5 == null) {
contentMd5 = "";
}
method = method.toUpperCase();
StringBuilder buf = new StringBuilder(
method.length() + accept.length() + gmtDate.length() + url.length() + contentType.length()
+ contentMd5.length());
return buf.append(method).append('\n').append(accept).append('\n').append(contentMd5).append('\n')
.append(contentType).append('\n').append(gmtDate).append('\n').append(url).toString();
}
public static String originalSign4Dataplus(String appSecret, String method, String accept, String gmtDate,
String url) throws Exception {
return originalSign4Dataplus(appSecret, method, accept, gmtDate, url, null, null);
}
public static String originalSign4Dataplus(String appSecret, String method, String accept, String gmtDate,
String url, String contentType, String contentMd5) throws Exception {
String signedString = signedString(method, accept, gmtDate, url, contentType, contentMd5);
return toHmacSHA1(signedString, appSecret);
}
@Deprecated public static String sign4Datapuls(String module, String appKey, String appSecret,
String method, String accept, String gmtDate, String url) throws Exception {
return sign4Dataplus(module, appKey, appSecret, method, accept, gmtDate, url);
}
public static String sign4Dataplus(String module, String appKey, String appSecret, String method,
String accept, String gmtDate, String url) throws Exception {
return sign4Dataplus(module, appKey, appSecret, method, accept, gmtDate, url, null, null);
}
@Deprecated public static String sign4Datapuls(String module, String appKey, String appSecret,
String method, String accept, String gmtDate, String url, String contentType, String contentMd5)
throws Exception {
return sign4Datapuls(module, appKey, appSecret, method, accept, gmtDate, url, contentType,
contentMd5);
}
public static String sign4Dataplus(String module, String appKey, String appSecret, String method,
String accept, String gmtDate, String url, String contentType, String contentMd5)
throws Exception {
String signedString = signedString(method, accept, gmtDate, url, contentType, contentMd5);
return doSign(module, appKey, appSecret, signedString);
}
public static String[] spliteSign4Dataplus(String signature) {
return spliteSign4Dtboost(signature);
}
enum HttpMethod {
/**
* HTTP METHOD
*/
GET(false), POST(true), PUT(true), DELETE(false), PATCH(true), HEAD(false), OPTIONS(false), TRACE(
false);
private final boolean needBody;
private HttpMethod(boolean needBody) {
this.needBody = needBody;
}
}
public static final class Md5CalculatedOutputStream extends OutputStream {
private boolean nocontent = true;
private final MessageDigest md;
private final boolean parseEmptyStream;
public Md5CalculatedOutputStream() throws NoSuchAlgorithmException {
this(false);
}
public Md5CalculatedOutputStream(boolean parseEmptyStream) throws NoSuchAlgorithmException {
md = MessageDigest.getInstance("md5");
this.parseEmptyStream = parseEmptyStream;
}
@Override public void write(int b) throws IOException {
if (nocontent) {
nocontent = false;
}
md.update((byte) b);
}
@Override public void write(byte b[]) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (b.length != 0) {
if (nocontent) {
nocontent = false;
}
md.update(b);
}
}
@Override public void write(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len)
< 0)) {
throw new IndexOutOfBoundsException();
} else if (len != 0) {
if (nocontent) {
nocontent = false;
}
md.update(b, off, len);
}
}
public String toMd5() {
if (nocontent) {
return parseEmptyStream ? EMPTY_STRING_MD5 : "";
}
return Base64.encodeBase64String(md.digest());
}
}
}
c. JS应用-自行计算签名
function sign(url, method, headers, appKey, appSecret, body) {
const appSecret = appSecret;
const md5 = function (buffer) {
return crypto.createHash('md5').update(buffer).digest('base64');
};
const sha1 = function (stringToSign, appSecret) {
return crypto.createHmac('sha1', AppSecret).update(stringToSign).digest().toString('base64');
};
body = body || {};
let bodymd5 = '';
if (body && _.size(body) && ['POST', 'PUT', 'PATCH'].indexOf(method.toUpperCase()) >= 0) {
bodymd5 = crypto.createHash('md5').update(Buffer.from(JSON.stringify(body))).digest('base64');
}
let stringToSign = method + '\n' + Url.parse(url).path + '\n' + headers.date;
if (bodymd5) {
stringToSign = stringToSign + '\n' + bodymd5;
}
let signature = sha1(stringToSign, appSecret);
let authHeader = `common-user-ak-v1 ${appKey}:${signature}`;
return authHeader;
}
文档内容是否对您有帮助?