Setiap permintaan HTTP dari Operasi API Layanan Log Sederhana harus melewati verifikasi keamanan untuk memastikan keamanan data log. Layanan Log Sederhana menggunakan pasangan AccessKey Alibaba Cloud dan algoritma enkripsi asimetris untuk memverifikasi permintaan API.
Catatan penggunaan
SDK Layanan Log Sederhana mengenkapsulasi semua Operasi API Layanan Log Sederhana. Anda dapat menggunakan SDK ini untuk memanggil operasi API secara efisien. SDK ini menandatangani permintaan secara otomatis dan mendukung berbagai bahasa pemrograman. Kami merekomendasikan penggunaan SDK untuk mengakses Layanan Log Sederhana. Untuk informasi lebih lanjut, lihat Ikhtisar SDK Layanan Log Sederhana.
Layanan Log Sederhana melakukan langkah-langkah berikut dalam proses verifikasi keamanan:
Mengidentifikasi pengguna yang mengirim permintaan API.
Sebelum mengirim permintaan API, pengguna harus menentukan pasangan AccessKey untuk menghasilkan tanda tangan digital. Layanan Log Sederhana menggunakan pasangan AccessKey untuk mengidentifikasi pengguna dan menerapkan kontrol akses.
Memeriksa apakah permintaan API telah dirusak selama transmisi.
Setelah menerima permintaan API, Layanan Log Sederhana menghitung tanda tangan digital dan membandingkannya dengan tanda tangan yang dihasilkan di sisi klien. Jika permintaan dirusak selama transmisi, kedua tanda tangan tidak cocok, sehingga verifikasi gagal.
Untuk menghasilkan tanda tangan digital untuk permintaan API, Anda harus menggunakan pasangan AccessKey. Untuk informasi lebih lanjut, lihat Pasangan AccessKey. Anda dapat menggunakan pasangan AccessKey yang ada atau membuat pasangan baru. Pastikan bahwa pasangan AccessKey enabled.
Berikut ini menjelaskan struktur permintaan dan proses menghitung tanda tangan. Bagian ini juga menyediakan kode contoh dalam berbagai bahasa pemrograman untuk menunjukkan cara menghasilkan tanda tangan.
Struktur permintaan
Tabel berikut menjelaskan bidang header HTTP yang diperlukan dari permintaan API yang valid. Anda harus menentukan pasangan nilai-kunci untuk bidang tersebut. Nilai-nilai bersifat peka huruf besar/kecil.
Bidang | Deskripsi | Contoh |
x-log-signaturemethod | Metode enkripsi permintaan. | hmac-sha1 |
x-log-apiversion | Versi API permintaan. | 0.6.0 |
Date | Header timestamp standar permintaan HTTP. Header mengikuti format waktu yang didefinisikan dalam RFC 822 atau RFC 1123 dan mewakili nilai waktu dalam GMT. Format: %a, %d %b %Y %H:%M:%S GMT. | Mon, 3 Jan 2010 08:33:47 GMT |
Content-MD5 | Nilai hash MD5 dari badan permintaan HTTP. Anda harus mengonversi nilai hash MD5 menjadi string heksadesimal. | 72A15D7DE7EE9E7BB86461FFEA9499 |
Authorization | Tanda tangan. Format: LOG accessKeyId:Signature. accessKeyId menentukan ID AccessKey. Signature menentukan string tanda tangan. Untuk informasi lebih lanjut tentang string tanda tangan, lihat Proses perhitungan tanda tangan. | LOG testAccessKeyId:RLETq4u7sWb3cssZIhsun**** |
Content-Type | Jenis badan permintaan HTTP. Jika tidak ada badan permintaan HTTP, Anda tidak perlu menambahkan bidang ini. | application/json |
Kode contoh berikut memberikan contoh permintaan HTTP yang ditandatangani:
POST /logstores/test-logstore/shards/0?action=split HTTP/1.1
Host: ali-test-project.cn-hangzhou.log.aliyuncs.com
Date: Tue, 23 Aug 2022 12:12:03 GMT
x-log-apiversion: 0.6.0
x-log-signaturemethod: hmac-sha1
Content-Length: 18
Content-Type: application/json
Content-MD5: 49DFDD54B01CBCD2D2AB5E9E5EE6B9B9
Authorization: LOG testAccessKeyId:RLETq4u7sWb3cssZIhsun****
{"hello": "world"}
Proses perhitungan tanda tangan
Bidang Authorization diperlukan dalam struktur tanda tangan. Bidang Authorization berada dalam format LOG accessKeyId:Signature, yang menggabungkan bidang AccessKeyId dan Signature. accessKeyId menentukan ID AccessKey, dan Signature menentukan string tanda tangan. Bagian ini menjelaskan cara membuat string tanda tangan untuk bidang Signature.
Pesan tanda tangan
String tanda tangan dihasilkan dengan mengenkripsi dan mengkodekan pesan tanda tangan. Gambar berikut menunjukkan cara membangun pesan tanda tangan.
Parameter | Deskripsi | Contoh |
method | Metode permintaan HTTP. Nilainya hanya dapat berisi huruf kapital. Nilai valid: GET, POST, PUT, dan DELETE. | GET |
Content-MD5 | Nilai hash MD5 dari badan permintaan HTTP. Anda harus mengonversi nilai tersebut menjadi string heksadesimal yang berisi huruf kapital. Jika tidak ada badan permintaan HTTP, nilainya adalah string kosong. | 49DFDD54B01CBCD2D2AB5E9E5EE6B9B9 |
Content-Type | Jenis badan permintaan HTTP. Jika tidak ada badan permintaan HTTP, nilainya bisa berupa string kosong. | application/json |
Date | String terformat dari waktu saat ini. String tersebut mengikuti format waktu yang didefinisikan dalam RFC 822 atau RFC 1123 dan mewakili nilai waktu dalam GMT. Format: %a, %d %b %Y %H:%M:%S GMT. | Mon, 3 Jan 2010 08:33:47 GMT |
Header | Bidang header yang diawali oleh x-log- atau x-acs-. Bidang-bidang tersebut adalah pasangan nilai-kunci, dan pasangan nilai-kunci diurutkan secara menaik berdasarkan kunci. Kunci dan nilai dalam pasangan nilai-kunci dihubungkan oleh titik dua (:). Pasangan nilai-kunci dipisahkan oleh baris baru. | |
Uri | Jalur permintaan. Nama domain dan parameter terkait query dikecualikan. | /logstores/test-logstore |
Parameter terkait query | Parameter terkait query. Parameter-parameter tersebut adalah pasangan nilai-kunci, dan pasangan nilai-kunci diurutkan secara menaik berdasarkan kunci. Kunci dan nilai dalam pasangan nilai-kunci dihubungkan oleh tanda sama dengan (=). Pasangan nilai-kunci dipisahkan oleh ampersand (&). | offset=1&size=10 |
Kode contoh berikut memberikan contoh pesan tanda tangan. Setiap baris diakhiri dengan baris baru, kecuali baris terakhir.
POST
1572A15D7DE7EE9E7BB86461FFEA9499
application/json
Tue, 23 Aug 2022 12:12:03 GMT
x-log-apiversion:0.6.0
x-log-bodyrawsize:0
x-log-signaturemethod:hmac-sha1
/logstores?offset=1&size=10
String tanda tangan
Proses mendapatkan string tanda tangan adalah sebagai berikut:
Dapatkan pesan tanda tangan.
Gunakan algoritma HMAC-SHA1 dan rahasia AccessKey untuk mengenkripsi pesan, lalu dapatkan nilai hash dari hasil enkripsi.
Kodekan nilai hash dalam Base64 untuk menghasilkan string tanda tangan.
Contoh
Bagian ini memberikan contoh tentang cara menandatangani permintaan API. ID AccessKey dan rahasia AccessKey berikut digunakan sebagai contoh untuk menggambarkan proses penandatanganan:
AccessKeyId = "bq2sjzesjmo86kq****"
AccessKeySecret = "4fdO2fTDDnZPU/L7CHNd****"
Contoh 1
Gunakan permintaan GET untuk mencantumkan semua Logstores dari proyek bernama ali-test-project. Kode contoh berikut menunjukkan permintaan HTTP yang perlu ditandatangani:
GET /logstores?logstoreName=&offset=0&size=1000 HTTP/1.1
Date: Mon, 09 Nov 2015 06:11:16 GMT
Host: ali-test-project.cn-hangzhou.log.aliyuncs.com
x-log-apiversion: 0.6.0
x-log-bodyrawsize:0
x-log-signaturemethod: hmac-sha1
Pesan tanda tangan berikut dihasilkan untuk permintaan:
GET
Mon, 09 Nov 2015 06:11:16 GMT
x-log-apiversion:0.6.0
x-log-bodyrawsize:0
x-log-signaturemethod:hmac-sha1
/logstores?logstoreName=&offset=0&size=1000
Permintaan GET tidak berisi badan permintaan HTTP. Oleh karena itu, nilai bidang Content-MD5 dan Content-Type adalah string kosong. String tanda tangan berikut dihasilkan dengan menggunakan rahasia AccessKey yang ditentukan:
jEYOTCJs2e88o+y5F4/S5I****
Kode contoh berikut menunjukkan permintaan HTTP yang ditandatangani:
GET /logstores?logstoreName=&offset=0&size=1000 HTTP/1.1
Date: Mon, 09 Nov 2015 06:11:16 GMT
Host: ali-test-project.cn-hangzhou.log.aliyuncs.com
x-log-apiversion: 0.6.0
x-log-bodyrawsize:0
x-log-signaturemethod: hmac-sha1
Authorization: LOG bq2sjzesjmo86kq35behupbq:jEYOTCJs2e88o+y5F4/S5I****
Contoh 2
Tulis log berikut ke Logstore bernama test-logstore dalam proyek bernama ali-test-project:
topic=""
time=1447048976
source="10.10.10.1"
"TestKey": "TestContent"
Kode contoh berikut menunjukkan permintaan HTTP yang perlu ditandatangani:
POST /logstores/test-logstore HTTP/1.1
Date: Mon, 09 Nov 2015 06:03:03 GMT
Host: ali-test-project.cn-hangzhou.log.aliyuncs.com
x-log-apiversion:0.6.0
x-log-bodyrawsize:50
x-log-signaturemethod:hmac-sha1
Content-MD5: 1DD45FA4A70A9300CC9FE7305AF2C494
Content-Length: 52
<Log diserialisasi menjadi byte stream dalam format Protobuf.>
Log diserialisasi menjadi byte stream dalam format Protocol Buffer (Protobuf), kemudian digunakan sebagai badan permintaan HTTP. Untuk informasi lebih lanjut tentang format Protobuf, lihat Pengkodean Data. Dalam permintaan, nilai bidang Content-Type adalah application/x-protobuf. Nilai bidang Content-MD5 adalah nilai hash MD5 dari badan permintaan HTTP. Pesan tanda tangan berikut dihasilkan untuk permintaan:
POST
1DD45FA4A70A9300CC9FE7305AF2C494
application/x-protobuf
Mon, 09 Nov 2015 06:03:03 GMT
x-log-apiversion:0.6.0
x-log-bodyrawsize:50
x-log-compresstype:lz4
x-log-signaturemethod:hmac-sha1
/logstores/ali-test-logstore
String tanda tangan berikut dihasilkan dengan menggunakan rahasia AccessKey yang ditentukan:
XWLGYHGg2F2hcfxWxMLiNk****
Kode contoh berikut menunjukkan permintaan HTTP yang ditandatangani:
POST /logstores/ali-test-logstore HTTP/1.1
Date: Mon, 09 Nov 2015 06:03:03 GMT
Host: ali-test-project.cn-hangzhou.log.aliyuncs.com
x-log-apiversion:0.6.0
x-log-bodyrawsize:50
x-log-compresstype:lz4
x-log-signaturemethod:hmac-sha1
Content-MD5: 1DD45FA4A70A9300CC9FE7305AF2C494
Content-Length: 52
Authorization: LOG bq2sjzesjmo86kq35behupbq:XWLGYHGg2F2hcfxWxMLiNk****
<Log diserialisasi menjadi byte stream dalam format Protobuf.>
Kode contoh
Kode Contoh dalam Java
Kode contoh berikut menggunakan pustaka pihak ketiga commons-codec. Tambahkan dependensi Maven berikut ke pom.xml:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
Kode contoh berikut memberikan contoh tentang cara menandatangani permintaan API:
package com.aliyun.openservices.log.http.signer;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
public class v1 {
public static String md5(byte[] bs) throws Exception {
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(bs);
String hex = new BigInteger(1, digest.digest()).toString(16).toUpperCase();
return new String(new char[32 - hex.length()]).replace("\0", "0") + hex;
}
public static String getDateString() {
DateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
df.setTimeZone(new SimpleTimeZone(0, "GMT"));
return df.format(new Date());
}
public static void sign(String method, String uri, String accessKeyId, String accessKeySecret,
Map<String, String> params,
Map<String, String> headers,
byte[] body) throws Exception {
int contentLength = 0;
String contentMD5 = "", message = "";
headers.put("x-log-apiversion", "0.6.0");
headers.put("x-log-signaturemethod", "hmac-sha1");
if (body != null && body.length > 0) {
contentLength = body.length;
contentMD5 = md5(body);
headers.put("Content-MD5", contentMD5);
}
String date = getDateString();
headers.put("Date", date);
headers.put("Content-Length", String.valueOf(contentLength));
message += method + "\n"
+ contentMD5 + "\n"
+ headers.getOrDefault("Content-Type", "") + "\n"
+ date + "\n";
// header
String headerStr = headers.entrySet().stream()
.filter(e -> e.getKey().startsWith("x-log-") || e.getKey().startsWith("x-acs-"))
.sorted(Map.Entry.comparingByKey())
.map(e -> String.format("%s:%s\n", e.getKey(), e.getValue()))
.collect(Collectors.joining(""));
message += headerStr;
// uri & params
message += uri;
if (params.size() > 0) {
message += "?";
}
message += params.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.map(e -> String.format("%s=%s", e.getKey(), e.getValue()))
.collect(Collectors.joining("&"));
// signature & authorization
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec(accessKeySecret.getBytes(StandardCharsets.UTF_8), "HmacSHA1"));
String signature = new String(Base64.encodeBase64(mac.doFinal(message.getBytes(StandardCharsets.UTF_8))));
String auth = "LOG " + accessKeyId + ":" + signature;
headers.put("Authorization", auth);
}
}
Kode Contoh dalam Python
Kode contoh berikut memberikan contoh tentang cara menandatangani permintaan API:
import base64
import hashlib
import hmac
import locale
from datetime import datetime
from typing import Dict, Tuple
def get_date():
try:
locale.setlocale(locale.LC_TIME, "C")
except Exception as ex:
pass
return datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
def sign(method: str, uri: str, access_key_id: str,
access_key_secret: str, params: Dict[str, str],
headers: Dict[str, str], body: bytes):
content_length = 0
content_md5, message = '', ''
headers["x-log-apiversion"] = "0.6.0"
headers["x-log-signaturemethod"] = "hmac-sha1"
if body is not None and len(body) > 0:
content_length = str(len(body))
content_md5 = hashlib.md5(body).hexdigest().upper()
headers['Content-MD5'] = content_md5
date = get_date()
headers['Date'] = date
headers['Content-Length'] = content_length
content_type = headers.get('Content-Type', '')
message += method + "\n" + content_md5 + \
"\n" + content_type + "\n" + date + "\n"
# header
filter_by_prefix = lambda t: t[0].startswith('x-log-') or t[0].startswith('x-acs-')
slsHeaders = list(filter(filter_by_prefix, headers.items()))
sort_by_key = lambda k: k[0]
for [k, v] in sorted(slsHeaders, key=sort_by_key):
message += k + ':' + v + "\n"
# uri and params
message += uri
message += '?' if len(params) > 0 else ''
sep = ''
for [k, v] in sorted(params.items(), key=sort_by_key):
message += sep + k + '=' + v
sep = '&'
# signature and authorization
hashed = hmac.new(access_key_secret.encode('utf8'),
message.encode('utf8'), hashlib.sha1).digest()
signature = base64.encodebytes(hashed).decode('utf8').rstrip()
auth = f'LOG {access_key_id}:{signature}'
headers['Authorization'] = auth
Kode Contoh dalam PHP
Kode contoh berikut memberikan contoh tentang cara menandatangani permintaan API:
<?php
// mengembalikan array header baru
function sign($method, $uri, $accessKeyId, $accessKeySecret, $params, $headers, $body)
{
$contentLength = 0;
$headers["x-log-apiversion"] = "0.6.0";
$headers["x-log-signaturemethod"] = "hmac-sha1";
if (!is_null($body) && strlen($body) > 0) {
$contentLength = strlen($body);
$contentMd5 = strtoupper(md5($body));
$headers["Content-MD5"] = $contentMd5;
}
// tanggal
setLocale(LC_TIME, 'en_US');
$date = gmdate('D, d M Y H:i:s \G\M\T', time());
$headers["Date"] = $date;
$headers["Content-Length"] = (string)$contentLength;
$contentType = isset($headers['Content-Type']) ? $headers['Content-Type'] : '';
$message = $method . "\n" . $contentMd5 . "\n" . $contentType . "\n" . $date . "\n";
// header
$filterHeaders = [];
foreach ($headers as $key => $val) {
if (str_starts_with($key, 'x-log-') || str_starts_with($key, 'x-acs-')) {
$filterHeaders[$key] = $val;
}
}
ksort($filterHeaders);
foreach ($filterHeaders as $key => $val) {
$message .= $key . ':' . $val . "\n";
}
// uri dan params
$message .= $uri;
if (sizeof($params) > 0) {
$message .= '?';
}
ksort($params);
$sep = '';
foreach ($params as $key => $val) {
$message .= $sep . $key . '=' . $val;
$sep = '&';
}
// signature & authorization
$signature = base64_encode(hash_hmac('sha1', $message, $accessKeySecret, TRUE));
$auth = 'LOG ' . $accessKeyId . ':' . $signature;
$headers['Authorization'] = $auth;
return $headers;
};
// contoh pemanggilan
$headers = sign(
'POST',
'/logstores/test-logstore',
'testAccessId',
'testAccessKey',
array(
"test" => "test",
"hello" => "world"
),
array(
"x-log-signaturemethod" => "hmac-sha1",
"x-log-bodyrawsize" => "0",
"x-log-apiversion" => "0.6.0"
),
'hello, world'
);
echo ($headers['Authorization']);
foreach ($headers as $key => $val) {
echo ($key . '=' . $val . "\n");
}
?>
Kode Contoh dalam Go
Kode contoh berikut memberikan contoh tentang cara menandatangani permintaan API:
package sls
import (
"crypto/hmac"
"crypto/md5"
"crypto/sha1"
"encoding/base64"
"fmt"
"sort"
"strconv"
"strings"
"time"
)
/*
* @param uri Jalur URI dari permintaan HTTP, tidak termasuk host dan parameter query, misalnya: /logstores/test-logstore
* @param headers Fungsi ini memodifikasi header, header harus bukan map kosong
* @param method Metode HTTP dalam huruf besar, misalnya: GET, POST, PUT, DELETE
*/
func Sign(method, uri, accessKeyID, accessKeySecret string, headers, queryParams map[string]string, body []byte) error {
var message, signature string
var contentMD5, contentType, date string
headers["x-log-apiversion"] = "0.6.0";
headers["x-log-signaturemethod"] = "hmac-sha1";
if len(body) > 0 {
contentMD5 = fmt.Sprintf("%X", md5.Sum(body))
headers["Content-MD5"] = contentMD5
}
date = time.Now().In(time.FixedZone("GMT", 0)).Format(time.RFC1123)
headers["Date"] = date
headers["Content-Length"] = strconv.Itoa(len(body))
if val, ok := headers["Content-Type"]; ok {
contentType = val
}
message += method + "\n" + contentMD5 + "\n" + contentType + "\n" + date + "\n"
// header
slsHeaders := make(map[string]string)
for k, v := range headers {
if strings.HasPrefix(k, "x-log-") || strings.HasPrefix(k, "x-acs-") {
slsHeaders[k] = v
}
}
forEachInOrder(slsHeaders, func(k, v string) {
message += k + ":" + v + "\n"
})
message += uri
if len(queryParams) > 0 {
message += "?"
}
sep := ""
forEachInOrder(queryParams, func(k, v string) {
message += sep + k + "=" + v
sep = "&"
})
// Signature = base64(hmac-sha1(UTF8-Encoding-Of(SignString),AccessKeySecret))
mac := hmac.New(sha1.New, []byte(accessKeySecret))
_, err := mac.Write([]byte(message))
if err != nil {
return err
}
signature = base64.StdEncoding.EncodeToString(mac.Sum(nil))
auth := fmt.Sprintf("LOG %v:%v", accessKeyID, signature)
headers["Authorization"] = auth
return nil
}
func forEachInOrder(m map[string]string, f func(k, v string)) {
var ss sort.StringSlice
for k := range m {
ss = append(ss, k)
}
ss.Sort()
for _, k := range ss {
f(k, m[k])
}
}
Kode Contoh dalam C#
Kode contoh berikut memberikan contoh tentang cara menandatangani permintaan API:
using System.Security.Cryptography;
using System.Text;
using StringMap = System.Collections.Generic.Dictionary<string, string>;
void sign(string method, string uri,
string accessKeyId, string accessKeySecret,
StringMap queryParams,
StringMap headers,
byte[] body
)
{
int contentLength = 0;
string contentMd5 = "", message = "";
headers["x-log-apiversion"] = "0.6.0";
headers["x-log-signaturemethod"] = "hmac-sha1";
if (body != null && body.Length > 0)
{
contentLength = body.Length;
contentMd5 = BitConverter.ToString(MD5.Create().ComputeHash(body)).Replace("-", "");
Console.WriteLine(contentMd5);
headers["Content-MD5"] = contentMd5;
}
string date = DateTime.Now.ToUniversalTime().ToString("R");
headers["Date"] = date;
headers["Content-Length"] = contentLength.ToString();
message += method + "\n"
+ contentMd5 + "\n"
+ headers.GetValueOrDefault("Content-Type", "") + "\n"
+ date + "\n";
var sortedHeader = from entry in headers orderby entry.Key ascending select entry;
// header
foreach (var entry in sortedHeader)
{
if (entry.Key.StartsWith("x-log-") || entry.Key.StartsWith("x-acs-"))
{
message += entry.Key + ":" + entry.Value + "\n";
}
}
// url & params
message += uri;
if (queryParams.Count() > 0)
{
message += "?";
}
var sortedParam = from entry in queryParams orderby entry.Key ascending select entry;
string sep = "";
foreach (var entry in sortedParam)
{
message += sep + entry.Key + "=" + entry.Value;
sep = "&";
}
var hmac = new HMACSHA1(Encoding.ASCII.GetBytes(accessKeySecret));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(message)));
var auth = "LOG " + accessKeyId + ":" + signature;
headers["Authorization"] = auth;
}
Kode Contoh dalam C++
Kode contoh berikut memberikan contoh tentang cara menandatangani permintaan API. Anda harus mengimplementasikan fungsi pembantu dalam kode berdasarkan kebutuhan bisnis Anda. File header adapter.h dalam kode contoh milik Simple Log Service SDK untuk C++. Kami merekomendasikan agar Anda menandatangani permintaan berdasarkan Simple Log Service SDK untuk C++. Untuk informasi lebih lanjut, lihat Memulai dengan Simple Log Service SDK untuk C++.
CodecTool::CalcMD5(string): menghitung nilai hash MD5 dan mengonversi nilai tersebut menjadi string heksadesimal yang berisi huruf kapital.
CodecTool::StartWith(string, string): memeriksa apakah sebuah string dimulai dengan string lain.
CodecTool::Base64Encode(string): mengkodekan string dalam Base64.
CodecTool::CalcHMACSHA1(string, string): menggunakan algoritma HMAC-SHA1 untuk menghitung nilai hash.
CodecTool::GetDateString(): mendapatkan string terformat dari waktu saat ini. Format: %a, %d %b %Y %H:%M:%S GMT. Contoh: Mon,3 Jan 2010 08:33:47 GMT.
#include <map>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "adapter.h"
using namespace std;
using aliyun_log_sdk_v6::CodecTool;
void Sign(const string& httpMethod, const string& uri,
map<string, string>& httpHeaders,
const map<string, string>& urlParams, const string& body,
const string& accessKeyId, const string& accessKeySecret)
{
string message;
string contentMd5, signature, contentType;
httpHeaders["x-log-apiversion"] = "0.6.0";
httpHeaders["x-log-signaturemethod"] = "hmac-sha1";
// 1. Content-Md5
if (!body.empty())
{
contentMd5 = CodecTool::CalcMD5(body);
httpHeaders["Content-Md5"] = contentMd5;
}
// 2. Date
string dateTime = CodecTool::GetDateString();
httpHeaders["Date"] = dateTime;
// 3. Content-Length
string contentLength = std::to_string(body.size());
httpHeaders["Content-Length"] = contentLength;
// 4. Content-Type
if (httpHeaders.find("Content-Type") != httpHeaders.end())
{
contentType = httpHeaders["Content-Type"];
}
message.append(httpMethod).append("\n");
message.append(contentMd5).append("\n");
message.append(contentType).append("\n");
message.append(dateTime).append("\n");
// 5. header
map<string, string> filteredHeaders;
for (auto it : httpHeaders)
{
string key = it.first, value = it.second;
if (CodecTool::StartWith(key, "x-log-") ||
CodecTool::StartWith(key, "x-acs-"))
{
filteredHeaders[key] = value;
}
}
for (auto it : filteredHeaders)
{
message.append(it.first).append(":").append(it.second);
message.append("\n");
}
// 6. uri and url params
message.append(uri);
if (urlParams.size() > 0) message.append("?");
for (auto it = urlParams.begin(); it != urlParams.end(); ++it)
{
if (it != urlParams.begin())
{
message.append("&");
}
message.append(it->first).append("=").append(it->second);
}
// 7.Signature
signature = CodecTool::Base64Enconde(
CodecTool::CalcHMACSHA1(message, accessKeySecret));
// 8. authorization
httpHeaders["authorization"] =
"LOG " + accessKeyId + ':' + signature;
}
Kode Contoh dalam TypeScript
Kode contoh berikut menggunakan pustaka pihak ketiga crypto-js. Jalankan perintah berikut untuk menginstal dependensi:
npm install crypto-js --save
Kode contoh berikut memberikan contoh tentang cara menandatangani permintaan API:
import CryptoJS from 'crypto-js'
export function sign(
method: string,
uri: string,
access_key_id: string,
access_key_secret: string,
params: Map<string, string>,
headers: Map<string, string>,
body: string | undefined
) {
let content_length = 0
let content_md5 = '',
message = ''
headers.set("x-log-apiversion", "0.6.0")
headers.set("x-log-signaturemethod", "hmac-sha1")
if (body !== undefined && body.length > 0) {
content_length = body.length
content_md5 = CryptoJS.MD5(body).toString(CryptoJS.enc.Hex).toUpperCase()
headers.set('Content-MD5', content_md5)
}
const date = new Date().toUTCString()
headers.set('Date', date)
headers.set('Content-Length', content_length.toString())
message +=
method +
'\n' +
content_md5 +
'\n' +
(headers.get('Content-Type') ?? '') +
'\n' +
date +
'\n'
// headers
const sort_by_key = (a: [string, string], b: [string, string]) =>
a[0].localeCompare(b[0])
const filter_by_prefix = (e: [string, string]) =>
e[0].startsWith('x-log-') || e[0].startsWith('x-acs-')
const header_str = [...headers.entries()]
.filter(filter_by_prefix)
.sort(sort_by_key)
.map((e) => e[0] + ':' + e[1] + '\n')
.join('')
message += header_str
// uri & query params
message += uri
if (params.size > 0) {
message += '?'
}
message += [...params.entries()]
.sort(sort_by_key)
.map((e) => e[0] + '=' + e[1])
.join('&')
// signature & authorization
const signature = CryptoJS.HmacSHA1(message, access_key_secret).toString(
CryptoJS.enc.Base64
)
const auth = 'LOG ' + access_key_id + ':' + signature
headers.set('Authorization', auth)
}
// example call
sign(
'POST',
'/logstores/test-logstore',
'testAccessId',
'testAccessKey',
new Map<string, string>([
['test', 'test'],
['hello', 'world'],
]),
new Map<string, string>([
['x-log-signaturemethod', 'hmac-sha1'],
['x-log-bodyrawsize', '0'],
['x-log-apiversion', '0.6.0'],
['Content-Type', 'application/json'],
]),
'hello, world'
)
Kode Contoh dalam Rust
Kode contoh berikut memberikan contoh nama dan versi pustaka dependensi:
[dependencies]
chrono = "0.4.19"
md5 = "0.7.0"
base64 = "0.13.0"
hmac-sha1 = "0.1.3"
Kode contoh berikut memberikan contoh tentang cara menandatangani permintaan API:
extern crate base64;
extern crate hmacsha1;
extern crate md5;
use chrono::Utc;
use std::collections::*;
pub fn sign(
method: &str,
uri: &str,
access_key_id: &str,
access_key_secret: &str,
params: &HashMap<String, String>,
headers: &mut HashMap<String, String>,
body: Option<Vec<u8>>,
) -> String {
let mut content_length = 0;
let mut content_md5 = String::from("");
headers.insert("x-log-apiversion".to_owned(), "0.6.0".to_owned());
headers.insert("x-log-signaturemethod".to_owned(), "hmac-sha1".to_owned());
if let Some(content) = body {
if content.len() > 0 {
content_length = content.len();
content_md5 = format!("{:X}", md5::compute(content));
headers.insert("Content-MD5".to_owned(), content_md5.clone());
}
}
headers.insert("Content-Length".to_owned(), content_length.to_string());
// date
let date = Utc::now().format("%a, %d %b %Y %H:%M:%S GMT").to_string();
headers.insert("Date".to_owned(), date.clone());
let mut message = "".to_owned();
let content_type = headers
.get(&"Content-Type".to_owned())
.cloned()
.unwrap_or(String::from(""));
message += format!("{}\n{}\n{}\n{}\n", method, content_md5, content_type, date).as_str();
// header
let mut sorted_header: Vec<_> = headers.iter().collect();
sorted_header.sort_by_key(|x| x.0);
for (k, v) in sorted_header {
if k.starts_with("x-log-") || k.starts_with("x-acs-") {
message += format!("{}:{}\n", k, v).as_str();
}
}
// url & params
message += uri;
if params.len() > 0 {
message += "?";
}
let mut sorted_params: Vec<_> = params.iter().collect();
sorted_params.sort_by_key(|x| x.0);
let mut sep = "";
for (k, v) in sorted_params {
message += format!("{}{}={}", sep, k, v).as_str();
sep = "&";
}
let signature = base64::encode(hmacsha1::hmac_sha1(
access_key_secret.as_bytes(),
message.as_bytes(),
));
let auth = format!("LOG {}:{}", access_key_id, signature);
headers.insert("Authorization".to_owned(), auth.to_owned());
auth
}