如何在请求前在 Swagger 中计算 AWS 签名 V4

How to calculate AWS signature V4 in Swagger before request

对于我们的 AWS API 端点,我们使用 AWS_IAM 授权并希望从 Swagger UI 进行调用。 要成功调用,必须有 2 headers 'Authorization' 和 'x-amz-date'。为了形成 'Authorization',我们使用 following steps from aws doc。 我们必须在每次调用时更改 'x-amz-date' 才能通过授权。 问题是:如何在 Swagger 中编写脚本来签署请求,每次 请求发送到 aws 之前 运行? (我们知道如何在加载 Swagger 页面之前指定一次 headers,但是这个过程应该在每次 调用之前 re-run

提前致谢。

swagger-js 中有 built-in 支持添加 requestInterceptor 来做到这一点。 swagger-ui 项目在后台使用 swagger-js。

像这样简单地创建一个请求拦截器:

requestInterceptor: {
  apply: function (request) {
    // modify the request object here
    return request;
  }
}

并在创建时将其应用于您的 swagger 实例:

window.swaggerUi = new SwaggerUi({
  url: url,
  dom_id: "swagger-ui-container",
  requestInterceptor: requestInterceptor,

这里可以在requestobject中设置headers(注意,这不是标准javascripthttp请求 object,检查它以获取详细信息)。但是您在这里确实可以访问所有 headers,因此您可以根据需要计算和注入它们。

您可以很容易地将 AWS SDK 中的签名 monkeypatch 签名到 SwaggerJS(以及 SwaggerUI)中。参见 here

我有一个稍微修改过的 SwaggerUI here。给定一些 AWS 凭证和一个 API ID,它将拉下 Swagger 定义,将其显示在 SwaggerUI 中,然后您可以使用 sigv4 调用 API。

A​​uthorizer 实现如下所示:

var AWSSigv4RequestSigner = function(credentialProvider, aws) {
  this.name = "sigv4";
  this.aws = aws;
  this.credentialProvider = credentialProvider;
};

AWSSigv4RequestSigner.prototype.apply = function(options, authorizations) {
  var serviceName = "execute-api";

  //If we are loading the definition itself, then we need to sign for apigateway.
  if (options && options.url.indexOf("apigateway") >= 0) {
    serviceName = "apigateway";
  }

  if(serviceName == "apigateway" || (options.operation && options.operation.authorizations && options.operation.authorizations[0].sigv4))
  {
    /**
     * All of the below is an adapter to get this thing into the right form for the AWS JS SDK Signer
     */
    var parts = options.url.split('?');
    var host = parts[0].substr(8, parts[0].indexOf("/", 8) - 8);
    var path = parts[0].substr(parts[0].indexOf("/", 8));
    var querystring = parts[1];

    var now = new Date();
    if (!options.headers)
    {
     options.headers = [];
    }

    options.headers.host = host;
    if(serviceName == "apigateway")
    {
      //For the swagger endpoint, apigateway is strict about content-type
      options.headers.accept = "application/json";
    }

    options.pathname = function () {
      return path;
    };
    options.methodIndex = options.method;
    options.search = function () {
      return querystring ? querystring : "";
    };
    options.region = this.aws.config.region || 'us-east-1';

    //AWS uses CAPS for method names, but swagger does not.
    options.method = options.methodIndex.toUpperCase();

    var signer = new this.aws.Signers.V4(options, serviceName);


    //Actually add the Authorization header here
    signer.addAuthorization(this.credentialProvider, now);

    //SwaggerJS/yourbrowser complains if these are still around
    delete options.search;
    delete options.pathname;
    delete options.headers.host;
    return true;
  }
  return false;
};