【问题标题】:Using AWS Gateway API, can I access the cookies?使用 AWS Gateway API,我可以访问 cookie 吗?
【发布时间】:2016-06-05 00:22:12
【问题描述】:

使用 HTTP 代理集成我想访问 cookie 并将一个添加到 json 响应中。这可能吗?

【问题讨论】:

  • 是的,这绝对是可能的。您可以访问所有请求参数(标头、查询字符串、路径、正文),并且可以使用集成请求中的映射模板将它们转换为 HTTP 后端。

标签: amazon-web-services aws-api-gateway


【解决方案1】:

要在后端访问客户端发送的 cookie,您必须设置从方法请求标头到集成请求标头的映射。

这些说明假设您已经在 API Gateway 中设置了一个简单的方法。

在您的后端访问 cookie

  1. 在方法请求下,创建一个名为“Cookie”的 HTTP 请求标头
  2. 在集成请求下,创建一个名为“Cookie”且“映射自”值为method.request.header.Cookie 的 HTTP 标头。
  3. 您可能还需要为此方法设置 CORS。见:http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html
  4. 部署您的 API 并使用您的浏览器/客户端向您的 API Gateway 端点发出请求。您应该会看到带有从浏览器发送的 Cookie 标头值进入 HTTP 后端的请求。

将 cookie 添加到响应中

您可以以类似的方式为方法配置的集成响应/方法响应端设置Set-Cookie 响应标头。

  1. 在方法响应下,创建一个名称为Set-Cookie 的响应标头
  2. 在集成响应下设置一个带有响应标头Set-Cookie 和映射值integration.response.header.Set-Cookie 的标头映射

请注意,此时 API Gateway 仅支持设置单个 Set-Cookie 响应标头。如果您的后端尝试设置多个 Set-Cookie 标头,则只会设置最后一个。有关详细信息,请参阅此论坛帖子:https://forums.aws.amazon.com/thread.jspa?messageID=701434

【讨论】:

  • 从逻辑上讲它应该会有所帮助,我也会做同样的事情。但是,如果日志中的 API 网关显示服务器未返回“Set-Cookie”标头,我该怎么办,即使我 100% 确定它确实如此。也许你以前也遇到过同样的问题?有任何想法吗?谢谢)
  • @SergeyPotapov 如果您在 localhost 上进行测试,它将不起作用,因为域不匹配。当您打开 lambda 的 url 本身时,它应该可以工作。如果不是这种情况,您将必须验证您的方法/集成响应
【解决方案2】:

如果您在 API Gateway 方法中选中“使用 Lambda 代理集成”选项,请求标头将通过 event 变量传递给您的 Lambda 函数。 API Gateway 也将期望来自您的回调函数的不同响应。此响应格式可用于指示 Set-Cookie 标头。例如:

callback(null, {
    statusCode: 200,
    headers: {'Set-Cookie': 'key=val'},
    body: 'Some response'
})`

这种方法的优点是不需要任何方法请求或方法响应调整。

这是一个示例 Lambda 函数,它使用此逻辑在每次请求后轮换 cookie 值。

exports.handler = (event, context, callback) => {

    var cookies = getCookiesFromHeader(event.headers);

    var old_cookie = cookies.flavor;
    var new_cookie = pickCookieFlavor(old_cookie);

    return callback(null, {
        statusCode: 200,
        headers: {
            'Set-Cookie': setCookieString('flavor', new_cookie),
            'Content-Type': 'text/plain'
        },
        body: 'Your cookie flavor was ' + old_cookie + '. Your new flavor is ' + new_cookie + '.'
    });
};

/**
 * Rotate the cookie flavor
 */
function pickCookieFlavor(cookie) {
    switch (cookie) {
        case 'peanut':
            return 'chocolate';
        case 'chocolate':
            return 'raisin and oat';
        default:
            return 'peanut';
    }
}

/**
 * Receives an array of headers and extract the value from the cookie header
 * @param  {String}   errors List of errors
 * @return {Object}
 */
function getCookiesFromHeader(headers) {

    if (headers === null || headers === undefined || headers.Cookie === undefined) {
        return {};
    }

    // Split a cookie string in an array (Originally found http://stackoverflow.com/a/3409200/1427439)
    var list = {},
        rc = headers.Cookie;

    rc && rc.split(';').forEach(function( cookie ) {
        var parts = cookie.split('=');
        var key = parts.shift().trim()
        var value = decodeURI(parts.join('='));
        if (key != '') {
            list[key] = value
        }
    });

    return list;
};


/**
 * Build a string appropriate for a `Set-Cookie` header.
 * @param {string} key     Key-name for the cookie.
 * @param {string} value   Value to assign to the cookie.
 * @param {object} options Optional parameter that can be use to define additional option for the cookie.
 * ```
 * {
 *     secure: boolean // Watever to output the secure flag. Defaults to true.
 *     httpOnly: boolean // Watever to ouput the HttpOnly flag. Defaults to true.
 *     domain: string // Domain to which the limit the cookie. Default to not being outputted.
 *     path: string // Path to which to limit the cookie. Defaults to '/'
 *     expires: UTC string or Date // When this cookie should expire.  Default to not being outputted.
 *     maxAge: integer // Max age of the cookie in seconds. For compatibility with IE, this will be converted to a
*          `expires` flag. If both the expires and maxAge flags are set, maxAge will be ignores. Default to not being
*           outputted.
 * }
 * ```
 * @return string
 */
function setCookieString(key, value, options) {
    var defaults = {
        secure: true,
        httpOnly: true,
        domain: false,
        path: '/',
        expires: false,
        maxAge: false
    }
    if (typeof options == 'object') {
        options = Object.assign({}, defaults, options);
    } else {
        options = defaults;
    }

    var cookie = key + '=' + value;

    if (options.domain) {
        cookie = cookie + '; domain=' + options.domain;
    }

    if (options.path) {
        cookie = cookie + '; path=' + options.path;
    }

    if (!options.expires && options.maxAge) {
        options.expires = new Date(new Date().getTime() + parseInt(options.maxAge) * 1000); // JS operate in Milli-seconds
    }

    if (typeof options.expires == "object" && typeof options.expires.toUTCString) {
        options.expires = options.expires.toUTCString();
    }

    if (options.expires) {
        cookie = cookie + '; expires=' + options.expires.toString();
    }

    if (options.secure) {
        cookie = cookie + '; Secure';
    }

    if (options.httpOnly) {
        cookie = cookie + '; HttpOnly';
    }

    return cookie;
}

【讨论】:

  • 代理集成从请求中去除 cookie 标头
  • 可以添加一件事,我尝试从 CloudFront 中的请求中获取 cookie(我使用 lambda 作为代理)。 cookie 的实际值实际上存储在event.Records[0].cf.request.headers.cookie[0].value 中,因此可能需要稍微更改函数才能找到 cookie。
猜你喜欢
  • 1970-01-01
  • 2022-11-10
  • 2021-06-19
  • 2020-02-20
  • 2011-06-12
  • 2019-03-17
  • 1970-01-01
  • 2020-11-12
  • 2011-12-15
相关资源
最近更新 更多