API的鉴权分为简单身份认证(Token)及签名认证(Signtures)两种,签名认证为安全性较高的方式,Token为使用较为简单的方式,您可根据自己的需求自行选择。
Token(简单身份认证)
滴滴云会在为每个订阅的服务生成APP Code,仅需要在HTTP请求的Headers中增加Authorization头部并其value设置为AppCode <app code>
即可进行访问
例:
curl -X POST \
http://dc286d9ff7285230a9b7149a871256ce.apigw-dev-gz.didiyunapi.com/test \
-H 'Authorization: AppCode ACDDCUqbLKjjC5KLcMAZk3qmeRmMsJFd'
Signtures(签名认证)
签名认证方式基于HTTP Signatures
在控制台的每个服务上均包含一个APP Key(KeyId)与APP Secret字段,该字段为用户与服务器均知晓的字段
用户请求时将请求的 地址、请求方法、时间等使用hmac-sha256进行加密,作为签名连同 keyId 一同放到header中发给服务器: 如
Authorization: Signature keyId="AKDD43nvRH3y7sUz373lZffyJr26Qo",signature="jKyvPcxB4JbmYY4mByyBY7cZfNl4OW9HpFQlG7N4YcJPteKTu4MW CLyk+gIr0wDgqtLWf9NLpMAMimdfsH7FSWGfbMFSrsVTHNTk0rK3usrfFnti1dx sM4jl0kYJCKTGI/UWkqiaxwNiKqGcdlEDrTcUhhsFsOIo8VhddmZTZ8w="
服务端收到请求后,会对Signature进行解密从而比对APP Secret等信息,如比对成功则表示鉴权成功,鉴权失败则会返回401错误。
该签名认证方案大多数语言均提供有SDK,下方给出了部分语言的示例代码供您参考
Python示例代码
# SDK参考:https://github.com/ahknight/drf-httpsig
# pip install requests drf-httpsig
import requests
from httpsig.requests_auth import HTTPSignatureAuth
APP_KEY = 'AKDD43nvRH3y7sUz373lZffyJr26Qo'
APP_SECRET = 'ASDDYN3qjl5GEcnRErQXgp1yJ7CKSoKJrakGXtFV'
URL = 'http://2b31803ec9fa.apigw-gz.didiyunapi.com/apimarket/test'
signature_headers = ['(request-target)', 'accept', 'date']
headers = {
'Accept': 'application/json',
'Date': 'Fri, 10 Jan 2020 15:17:06 CST',
}
print(headers)
auth = HTTPSignatureAuth(key_id=APP_KEY, secret=APP_SECRET,
algorithm='hmac-sha256',
headers=signature_headers)
req = requests.post(URL, auth=auth, headers=headers)
print(req)
Golang示例代码
// SDK参考:https://github.com/go-fed/httpsig
// go get "github.com/go-fed/httpsig"
package main
import (
"crypto"
"fmt"
"github.com/go-fed/httpsig"
"net/http"
"time"
)
const (
APP_KEY = "AKDD43nvRH3y7sUz373lZffyJr26Qo"
APP_SECRET = "ASDDYN3qjl5GEcnRErQXgp1yJ7CKSoKJrakGXtFV"
)
const (
METHOD = http.MethodPost
URL = "http://2b31803ec9fa.apigw-gz.didiyunapi.com/apimarket/test"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest(METHOD, URL, nil)
if err != nil {
panic(err)
}
req.Header.Add("date", time.Now().Format(time.RFC1123))
// 将签名信息注入至req对象中
if err := SignRequest(APP_KEY, APP_SECRET, req);err != nil {
panic(err)
}
resp, err := client.Do(req)
fmt.Println(resp)
}
func SignRequest(APPKey string, APPSecret string, r *http.Request) error {
privateKey := crypto.PrivateKey([]byte(APPSecret))
prefs := []httpsig.Algorithm{httpsig.HMAC_SHA256}
headersToSign := []string{"date"}
signer, _, err := httpsig.NewSigner(prefs, headersToSign, httpsig.Authorization)
if err != nil {
return err
}
return signer.SignRequest(privateKey, APPKey, r)
}
Java示例代码
// SDK 参考:https://github.com/tomitribe/http-signatures-java
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.tomitribe.auth.signatures.Signature;
import org.tomitribe.auth.signatures.Signer;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.Key;
import java.text.SimpleDateFormat;
import java.util.*;
public class Demo {
final static String url = "http://2b31803ec9fa.apigw-gz.didiyunapi.com/apimarket/test";
final static String method = "post";
final static String appKey = "AKDD43nvRH3y7sUz373lZffyJr26Qo";
final static String appSecret = "ASDDYN3qjl5GEcnRErQXgp1yJ7CKSoKJrakGXtFV";
public static void main(String[] args) {
Map<String, String> headers = new HashMap<>();
headers.put("Accept", "application/json");
headers.put("Date", getServerTime());
String signature;
try {
signature = GetSignature(appKey, appSecret, method, url, headers);
} catch (IOException e) {
e.printStackTrace();
return;
}
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url).post(RequestBody.create(new byte[0]))
.header("Accept", headers.get("Accept"))
.header("Date", headers.get("Date"))
.header("Authorization", signature)
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.code());
} catch (IOException e) {
e.printStackTrace();
}
}
static String GetSignature (String keyId, String secret, String method, String uri, Map<String, String> headers) throws IOException {
final Signature signature = new Signature(keyId, "hmac-sha256", null, headers.keySet().toArray(new String[0]));
final Key key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
Signer signer = new Signer(key, signature);
Signature sign = signer.sign(method, uri, headers);
return sign.toString();
}
static String getServerTime() {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat(
"EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
return dateFormat.format(calendar.getTime());
}
}