简体   繁体   English

通过 Postman 进行 HMAC 认证

[英]HMAC authentication via Postman

I'm using an example for setting up HMAC authentication for a Web API project.我正在使用一个示例为 Web API 项目设置 HMAC 身份验证。 The original example source code/project is available here:原始示例源代码/项目可在此处获得:

http://bitoftech.net/2014/12/15/secure-asp.net-web-api-using-api-key-authentication-hmac-authentication/ http://bitoftech.net/2014/12/15/secure-asp.net-web-api-using-api-key-authentication-hmac-authentication/

I'm trying to get Postman to construct and send a GET request in it's pre-request script.我试图让 Postman 在它的预请求脚本中构造和发送 GET 请求。 However the request always fails with a 401 and I can't figure out why.但是请求总是失败并显示 401,我不知道为什么。
Postman pre-request script: Postman预请求脚本:

var AppId = "4d53bce03ec34c0a911182d4c228ee6c";
var APIKey = "A93reRTUJHsCuQSHR+L3GxqOJyDmQpCgps102ciuabc=";
var requestURI = "http%3a%2f%2flocalhost%3a55441%2fapi%2fv1%2fdata";
var requestMethod = "GET";
var requestTimeStamp = "{{$timestamp}}";
var nonce = "1";
var requestContentBase64String = "";

var signatureRawData  = AppId + requestMethod + requestURI + requestTimeStamp +  nonce + requestContentBase64String; //check
var signature = CryptoJS.enc.Utf8.parse(signatureRawData);
var secretByteArray = CryptoJS.enc.Base64.parse(APIKey);
var signatureBytes = CryptoJS.HmacSHA256(signature,secretByteArray)

var requestSignatureBase64String = CryptoJS.enc.Base64.stringify(signatureBytes);
postman.setGlobalVariable("key", "amx " + AppId + ":" + requestSignatureBase64String + ":" + nonce + ":" + requestTimeStamp);

This is the code I'm using in my Pre-Script.这是我在 Pre-Script 中使用的代码。 It works for any query GET, PUT, POST, DELETE.它适用于任何查询 GET、PUT、POST、DELETE。

You need to change the AppId & the APIKey values and on the last line adjust the name of the environment variable "hmacKey" with yours.您需要更改 AppId 和 APIKey 值,并在最后一行用您的名称调整环境变量“hmacKey”的名称。

function interpolate (value) {
    const {Property} = require('postman-collection');
    return Property.replaceSubstitutions(value, pm.variables.toObject());
}

var uuid = require('uuid');
var moment = require("moment")

var hmacPrefix = "hmac";
var AppId = "4d53bce03ec34c0a911182d4c228ee6c";
var APIKey = "A93reRTUJHsCuQSHR+L3GxqOJyDmQpCgps102ciuabc=";
var requestURI = encodeURIComponent(pm.environment.values.substitute(pm.request.url, null, false).toString().toLowerCase());
var requestMethod = pm.request.method;
var requestTimeStamp = moment(new Date().toUTCString()).valueOf() / 1000;
var nonce = uuid.v4();
var requestContentBase64String = "";
var bodyString = interpolate(pm.request.body.toString());

if (bodyString) {
    var md5 = CryptoJS.MD5(bodyString);
    requestContentBase64String = CryptoJS.enc.Base64.stringify(md5);
}

var signatureRawData  = AppId + requestMethod + requestURI + requestTimeStamp +  nonce + requestContentBase64String; //check
var signature = CryptoJS.enc.Utf8.parse(signatureRawData);
var secretByteArray = CryptoJS.enc.Base64.parse(APIKey);
var signatureBytes = CryptoJS.HmacSHA256(signature,secretByteArray);
var requestSignatureBase64String = CryptoJS.enc.Base64.stringify(signatureBytes);

var hmacKey = hmacPrefix + " " + AppId + ":" + requestSignatureBase64String + ":" + nonce + ":" + requestTimeStamp;
postman.setEnvironmentVariable("hmacKey", hmacKey);

After a few days of testing I figured out the problem.经过几天的测试,我找到了问题所在。 It was actually to do with the variable placeholders provided by Postman of all things.它实际上与 Postman 提供的所有事物的可变占位符有关。 In testing the placeholder {{$timestamp}} at face value was passing a valid value.在测试占位符 {{$timestamp}} 的面值时传递了一个有效值。 When I stripped the signature back to start with just a single segment I was getting authenticated successfully.当我剥离签名以仅从一个段开始时,我成功地进行了身份验证。 Until of course I put the timestamp placeholder back in.当然,直到我把时间戳占位符放回去。

When I swapped out the placeholder for the actual value passed in the header it worked fine.当我将占位符换成标题中传递的实际值时,它工作正常。 I can only conclude that there must be some extra character I can't see.我只能得出结论,一定有一些我看不到的额外字符。 Perhaps on the Postman side when it creates the signature.也许在邮递员方面创建签名时。 The problem extends to other placeholders such as {{$guid}}.该问题扩展到其他占位符,例如 {{$guid}}。

If you are having trouble with the script provided by Florian SANTI and you are using Postman v8.0 or higher.如果您在使用Florian SANTI提供的脚本时遇到问题,并且您使用的是 Postman v8.0 或更高版本。 You'll need to make sure that the empty string is set by the variable requestContentBase64String is set properly by correctly inspecting the request body.您需要确保通过正确检查请求正文来正确设置变量 requestContentBase64String 设置的空字符串。

This is how I solved the issue.这就是我解决问题的方法。

var uuid = require('uuid');
var moment = require("moment")
var AppId = "4d53bce03ec34c0a911182d4c228ee6c";
var APIKey = "A93reRTUJHsCuQSHR+L3GxqOJyDmQpCgps102ciuabc=";
var requestURI = encodeURIComponent(pm.environment.values.substitute(pm.request.url, null, false).toString()).toLowerCase();
var requestMethod = pm.request.method;
var requestTimeStamp = moment(new Date().toUTCString()).valueOf() / 1000;
var nonce = uuid.v4();

var hasBody = (pm.request.body !== null);
if (hasBody) {
    hasBody = (!pm.request.body.isEmpty);
}
var requestContentBase64String = "";
if (hasBody) {
    var md5 = CryptoJS.MD5(JSON.stringify(postBody));
    requestContentBase64String = CryptoJS.enc.Base64.stringify(md5);
}

var signatureRawData  = AppId + requestMethod + requestURI + requestTimeStamp +  nonce + requestContentBase64String; //check
var signature = CryptoJS.enc.Utf8.parse(signatureRawData);
var secretByteArray = CryptoJS.enc.Base64.parse(APIKey);
var signatureBytes = CryptoJS.HmacSHA256(signature,secretByteArray);
var requestSignatureBase64String = CryptoJS.enc.Base64.stringify(signatureBytes);
var hmacKey =  "amx " + AppId + ":" + requestSignatureBase64String + ":" + nonce + ":" + requestTimeStamp;
postman.setEnvironmentVariable("hmacKey", hmacKey );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM