Postman fulfill the request through the API Gateway signature and debugging

1 Introduction

Postman is a very powerful tool for testing HTTP contract, currently Postman has provided the client Windows / Mac / Linux system downloads, very easy to use. But API debugging Gateway, the need for an HTTP request is signed to calls, you can not use a simple curl and other contracting tools to complete, but we can use the Pre-request Script scripting Postman tools to achieve the signature features of the API gateway, enabling a debugging API's Features.

2. API Gateway signature algorithm introduced

Signature mechanism API gateway reference may sign the request documentation , a brief overview here.

Signature API Gateway needs through the API Gateway AppKey and AppSecret conduct, Key / Secret available on the API gateway console and ensure that the API has been released, and made unauthorized operation for a particular APP.

For a general request, following the signing process API Gateway

2.1. Add the following first aid for signature and safety certification

- Date: 日期头
- X-Ca-Key:{AppKey} 
- X-Ca-Nonce:API调用者生成的 UUID, 实现防重放功能
- Content-MD5: 当请求Body为非Form表单时,用于校验Body是否被篡改, 

2.2 The organization needs a signature string StringToSign

{HTTPMethod} + "\n" + 
{Accept} + "\n" +
{Content-MD5} + "\n" 
{Content-Type} + "\n" + 
{Date} + "\n" + 
{SignatureHeaders} + 
{UrlToSign}
  • Accept, Content-MD5, Content-Type, Date If you need to add an empty line breaks "n"
  • From the form of non-only manner only need to calculate the Content-MD5, calculated as base64Encode (md5 (body.getBytes ( "UTF-8"))
  • SignatureHeaders: In {HeaderName}: {HeaderValue} + "n" sequential manner in accordance with the ascending order of the string is added, it is recommended to add a signature of the first X-Ca-Key, X-Ca-Nonce, other implementations may first client choose whether to join the signatures.
  • UrlToSign: Form fields all fields QueryString together and sorted by Name, if not the Content-Type application / x-www-form-urlencoded not Form Type field apart. The sorted key-value pair added back to give Path UrlToSign, such as request / demo? C = 1 & a = 2, Form is b = 3 then the UrlToSign = / demo? A = 2 & b = 3 & c = 1

2.3 Calculation of additional signatures and signature-related Headers

Currently recommended HMacSHA256 signature algorithm to calculate the required signature appSecret, calculated as: signature = base64 (hmacSHA256 (stringToSign.getBytes ( "UTF-8), appSecret)), is calculated after the completion also need to add the following Headers:

  • Add Header: X-Ca-Siguature: {signature}
  • Add Header: X-Ca-SignatureMethod: HmacSHA256
  • 添加Header: X-Ca-SignatureHeaders:X-Ca-Key,X-Ca-Nonce

2.4. Signature error troubleshooting methods

  • When signature verification fails, StringToSign API Gateway service will end into Header HTTP response is returned to the client, Key to: X-Ca-Error-Message, just to the local and server computing StringToSign returned StringToSign compare to find the problem, attention returned from the server StringToSign will replace carriage returns to #;
  • If the signature string and client service is consistent, check the key for the signature computation is correct;

3. Pre-request Script achieve Signature Algorithm

According to the description on one of the key issues to achieve the API Gateway Debugging is how to fulfill the request signature, Postman offers can be customized by JavaScript, by reading Pre-request Script development documents, we can implement the API by Pre-request Script script signature function gateway.

Note: Please use this section POSTMAN Version 7.2.0 or later

3.1 The use of global variables need to add pre-signature header

But now Postman not allowed to modify the request directly in the script, so we can only use pre-signing head and use a global variable assignment is completed add a signature header, we will need the signature of the head are prefabricated at the request Header Postman, you can Bulk Edit mode implemented added, Bulk Edit Referring next to FIG switching

d727c94c4c8e06ab51617de54a6cab63

After switching to Bulk Edit mode, the following string can copy and paste into the input box which is enclosed in {} is Postman global variables, we replace the realization in the script. Form contents can not add Content-MD5 header

Date:{{Date}}
Content-MD5:{{Md5}}
X-Ca-Nonce:{{Nonce}}
X-Ca-Key:{{AppKey}}
X-Ca-Signature:{{Signature}}
X-Ca-SignatureMethod:HmacSHA256
X-Ca-Signature-Headers:{{SignatureHeaders}}

FIG effect after pasting

bb92849f4ac664de833fe110a9f4f032

3.2 Use Pre-request Script scripting implement signature function

Click the red circle encircled position, enter Pre-request Script, copy and paste the code into the text box provided below them

Note: Please use this section POSTMAN Version 7.2.0 or later

311199754a861386c03e41f361ecc5ac

var appKey = "YOUR APPKEY";
var appSecret = "YOUR APPCODE";
var md5 = calcMd5();
var dateObject = Date;
var date = dateObject.toLocaleString();
var nonce = createUuid();
var textToSign = "";
var accept = "*/*";
var contentType = "";
console.log("request" + JSON.stringify(request));
if(request.headers["accept"]){
    accept = request.headers["accept"];
}
if(request.headers["content-type"]){
    contentType = request.headers["content-type"];
}
textToSign += request.method + "\n";
textToSign += accept + "\n";
textToSign += md5 + "\n";
textToSign += contentType + "\n";
textToSign += date + "\n";
var headers = headersToSign();
var signatureHeaders;
var sortedKeys = Array.from(headers.keys()).sort()
for (var headerName of sortedKeys) {
    textToSign += headerName + ":" + headers.get(headerName) + "\n";
    signatureHeaders = signatureHeaders ? signatureHeaders + "," + headerName : headerName;
}
textToSign += urlToSign();
console.log("textToSign\n" + textToSign.replace(/\n/g, "#"));
var hash = CryptoJS.HmacSHA256(textToSign, appSecret)
console.log("hash:" + hash)
var signature = hash.toString(CryptoJS.enc.Base64)
console.log("signature:" + signature)
pm.globals.set('AppKey', appKey);
pm.globals.set('Md5', md5);
pm.globals.set("Date", date);
pm.globals.set("Signature", signature);
pm.globals.set("SignatureHeaders", signatureHeaders);
pm.globals.set("Nonce", nonce);
function headersToSign() {
    var headers = new Map();
    for (var name in request.headers) {
        name = name.toLowerCase();
        if (!name.startsWith('x-ca-')) {
            continue;
        } 
        if (name === "x-ca-signature" || name === "x-ca-signature-headers" || name == "x-ca-key" || name === 'x-ca-nonce') {
            continue;
        }
        var value = request.headers[name];
        headers.set(name, value);
    }
    headers.set('x-ca-key', appKey);
    headers.set('x-ca-nonce', nonce);
    return headers;
}
function urlToSign() {
    var params = new Map();
    var contentType = request.headers["content-type"];
    if (contentType && contentType.startsWith('application/x-www-form-urlencoded')) {
       for(x in request.data){
           params.set(x, request.data[x]);
       }
    }
    var queryParam = pm.request.url.query.members;
    console.log("request.url" + JSON.stringify(pm.request.url))
    for (let i in queryParam) {
        params.set(queryParam[i].key, queryParam[i].value);
    }
    var sortedKeys = Array.from(params.keys())
    sortedKeys.sort();
    var url = "";
    for(var k of pm.request.url.path){
        url = url + "/" + k;
    }
    var qs;
    for (var k of sortedKeys) {
        var s = k + "=" + params.get(k);
        qs = qs ? qs + "&" + s : s;
        console.log("key=" + k + " value=" + params.get(k));
    }
    return qs ? url + "?" + qs : url;
}
function calcMd5() {
    var contentType = String(request.headers["content-type"]);
    console.log("data" + JSON.stringify(request.data));
    if (!JSON.stringify(request.data).startsWith('{}') && !contentType.startsWith('application/x-www-form-urlencoded')) {
        var data = request.data;
        var md5 = CryptoJS.MD5(data);
        var md5String = md5.toString(CryptoJS.enc.Base64);
        console.log("data:" + data + "\nmd5:" + md5String);
        return md5String;
    } else {
        return "";
    }
}
function createUuid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
        return v.toString(16);
    });
}

Then we can realize the debugging API Gateway.

Note that this section of code only for reference. There will be circumstances user feedback POSTMAN "Can not get any response" when WINDOWS platform to run this script, it is recommended that users try to use POSTMAN debugging in MAC environment.

Guess you like

Origin yq.aliyun.com/articles/753758