当前位置: 首页 > 知识库问答 >
问题:

Postman-在请求前脚本中访问完整的请求主体(以计算哈希)

羿宏硕
2023-03-14

我试图在PostMan中重新创建C#委托处理程序
我已经创建了计算auth头值的请求前脚本。

目前我的脚本是这样的:

function S4() {
    return (((1+Math.random())*0x10000)|0).toString(16).substring(1); 
}

function GetNonce() {
    return (S4() + S4() + S4()+ S4() + S4() + S4() + S4()+ S4()).toLowerCase();
}

function GetTimeStamp() {
    var d = new Date();
    return Math.round(d.getTime() / 1000);
}

function getAuthHeader(httpMethod, requestUrl, requestBody) {
    var CLIENT_KEY = postman.getEnvironmentVariable('hmac_user');
    var SECRET_KEY = postman.getEnvironmentVariable('hmac_key');
    var AUTH_TYPE = 'HMAC';

    requestUrl = requestUrl.replace(/{{(\w*)}}/g,function(str,key) {return environment[key]});
    requestUrl = requestUrl.toLowerCase();
    var requestTimeStamp = GetTimeStamp();
    var nonce = GetNonce();
    var bodyHash="";

    if (httpMethod == 'GET' || !requestBody) {
        requestBody = ''; 
    } else {
        var md5 = CryptoJS.MD5(requestBody);
        bodyHash = CryptoJS.enc.Base64.stringify(md5);
    }  

    var signatureRawData = [CLIENT_KEY, requestUrl, httpMethod, requestTimeStamp, nonce, bodyHash].join("");

    var key = CryptoJS.enc.Base64.parse(SECRET_KEY);
    var hash = CryptoJS.HmacSHA512(signatureRawData, key);
    var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);

    var header = [CLIENT_KEY, hashInBase64, nonce, requestTimeStamp].join(":");

    return AUTH_TYPE+" "+header;
}

postman.setEnvironmentVariable('hmacAuthHeader', getAuthHeader(request.method, request.url, request.data));

这非常适合没有任何正文的GET请求。但是,当我发送x-ww-form-urlen code请求时,由于C#和Postman中的正文哈希差异,我收到了未经授权的响应(401)。

我正在尝试访问完整的请求体,因为我需要计算出它的散列值。

我有C#的工作代码,而不是我想用Postman重新创建相同的请求。

我的问题是:
如何在请求前脚本中访问完整的请求正文?

我在C#中使用了这段代码,它运行得很好:

internal class HmacClientHandler : DelegatingHandler
{
    private readonly string _applicationId;
    private readonly string _applicationKey;

    public HmacClientHandler(string appId, string appKey)
    {
        _applicationId = appId;
        _applicationKey = appKey;
    }

    protected override async Task<HttpResponseMessage>SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)
    {
        HttpResponseMessage response = null;
        string url = Uri.EscapeUriString(request.RequestUri.ToString().ToLowerInvariant());
        string methodName = request.Method.Method;

        DateTime epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc);
        TimeSpan timeSpan = DateTime.UtcNow - epochStart;
        string requestTimeStamp = Convert.ToUInt64(timeSpan.TotalSeconds).ToString();
        string nonce = Guid.NewGuid().ToString("N");

        string contentBase64String = string.Empty;

        if (request.Content != null)
        {
            byte[] content = await request.Content.ReadAsByteArrayAsync();
            MD5 md5 = MD5.Create();
            byte[] hash = md5.ComputeHash(content);
            contentBase64String = Convert.ToBase64String(hash);
        }

        string authenticationKeyString = string.Format("{0}{1}{2}{3}{4}{5}", _applicationId, url, methodName, requestTimeStamp, nonce, contentBase64String);
        var secretKeyBase64ByteArray = Convert.FromBase64String(_applicationKey);

        using (HMACSHA512 hmac = new HMACSHA512(secretKeyBase64ByteArray))
        {
            byte[] authenticationKeyBytes = Encoding.UTF8.GetBytes(authenticationKeyString);
            byte[] authenticationHash = hmac.ComputeHash(authenticationKeyBytes);
            string hashedBase64String = Convert.ToBase64String(authenticationHash);
            request.Headers.Authorization = new AuthenticationHeaderValue("HMAC", string.Format("{0}:{1}:{2}:{3}", _applicationId, hashedBase64String, nonce, requestTimeStamp));
        }

        response = await base.SendAsync(request, cancellationToken);
        return response;
    }
}

共有1个答案

弘兴言
2023-03-14

前面引用的问题(#1050)似乎只适用于二进制/文件模式下的请求体(RequestBody.MODES.file)。请求体API提供了我对类似用例所需的东西:https://www.postmanlabs.com/postman-collection/RequestBody.html

我相信,如果你在预请求脚本中引用pm.request.body,它将提供你正在寻找的内容。具体来说,pm.request.body.toString() 似乎提供了最终将出现在请求中的实际 x-www-url-encoding 字符串(尽管,如果您在请求参数中使用环境变量,这些变量将在未解析的情况下发出,例如 {{variable_name}})。

因此,对于上面的脚本,我将最后一行改为:

postman.setEnvironmentVariable('hmacAuthHeader', getAuthHeader(request.method, request.url, pm.request.body.toString()));

...这似乎提供了一个可信的HMAC。一定要注意哈希/HMAC协议的所有规则,包括参数排序、空白处理等。

此外,我不确定<code>RequestBody</code>API是否在Postman的所有化身中都可用,但在我的原生Windows和OS X版本上运行良好。希望这有帮助!

 类似资料:
  • 我正在用Application/JSON数据发送原始POST请求到邮递员服务器。我需要使用这个JSON对象,并在请求前脚本中追加一些数据。但是我只能找到如何访问环境变量,而不能请求主体。有人知道吗?谢了!

  • 我正试图根据API验证自己。这个API使用来自请求的原始主体来创建哈希,它将使用该哈希对我的令牌进行身份验证。 出于测试目的,我使用postman和一个请求前脚本来创建哈希。一切都很好,只有一个例外: 在代码选项卡中,我有 谢了!

  • 我创建了一个spring boot应用程序,我的控制器就是这样的。我使用postman在请求体中发送json,在请求头中发送字符串,然后进一步对json进行散列,并将其与请求头获得的字符串进行比较。问题是,我不知道为了使用MockMvc测试相应的控制器类而获取请求体和请求头。 控制器逻辑 测试逻辑 请在上面的代码中帮助我从请求中检索body和header值,并将hash(body)与header值

  • 我正在尝试发送一个经过身份验证的请求,只需点击邮递员。 所以,我有一个名为“Oauth”的请求,我正在使用测试将令牌存储在局部变量中。 我现在要做的是,对于需要承载令牌的任何其他请求,自动运行Oauth请求(从预请求脚本)。 有没有一种方法可以通过单击邮递员按钮来获取访问令牌并发送经过身份验证的请求?

  • 我有一个对服务器的Authenticate post调用,如下所示: 用这样的尸体: 我总是必须在Postman中执行两次这个Authenticate调用,以正确填充我的全局var“安全令牌”,并在此后的下一次调用中使用该令牌进行身份验证,因此,似乎预请求脚本实际上是在脚本之后运行的,或者是预请求脚本中设置的全局var对当前请求不容易可用? 我做错了什么? 以下是预先请求的SRIPT:

  • 问题内容: 将请求正文与GET请求一起传递是否违反REST风格? 例如在Elasticsearch中过滤一些信息 甚至设计了一些工具来避免GET请求中的请求主体(例如邮递员) 问题答案: 从RFC: GET请求消息中的有效负载没有定义的语义。在GET请求上发送有效内容正文可能会导致某些现有实现拒绝该请求。 换句话说,这不是禁止的,但是它是未定义的行为,应避免使用。HTTP客户端,服务器和代理可以随