在 NodeJS 中使用 Lambda@Edge 对 CloudFront 进行基本 HTTP 身份验证
Posted
技术标签:
【中文标题】在 NodeJS 中使用 Lambda@Edge 对 CloudFront 进行基本 HTTP 身份验证【英文标题】:Basic HTTP Authentication for CloudFront with Lambda@Edge in NodeJS 【发布时间】:2021-10-05 10:14:19 【问题描述】:我正在使用用户名和密码保护静态网站。我在 NodeJS 中使用 Lambda@Edge 为 CloudFront 创建了一个基本的 HTTP 身份验证。
我对 NodeJS 完全陌生。最初,我对用户和密码进行了硬编码,并且工作正常。
'use strict';
exports.handler = (event, context, callback) =>
// Get request and request headers
const request = event.Records[0].cf.request;
const headers = request.headers;
// Configure authentication
const authUser = 'user';
const authPass = 'pass';
// Construct the Basic Auth string
const authString = 'Basic ' + new Buffer(authUser + ':' + authPass).toString('base64');
// Require Basic authentication
if (typeof headers.authorization == 'undefined' || headers.authorization[0].value != authString)
const body = 'Unauthorized';
const response =
status: '401',
statusDescription: 'Unauthorized',
body: body,
headers:
'www-authenticate': [key: 'WWW-Authenticate', value:'Basic']
,
;
callback(null, response);
// Continue request processing if authentication passed
callback(null, request);
;
我将我的秘密存储在 SSM 中,我想通过该函数检索它们。我在 Lambda 中单独测试了这段代码,它按预期返回了凭据。
'use strict';
exports.handler = async (event, context, callback) =>
const ssm = new (require('aws-sdk/clients/ssm'))();
let userData = await ssm.getParameters(Names: ['website-user']).promise();
let userPass = await ssm.getParameters(Names: ['website-pass']).promise();
let user = userData.Parameters[0].Value;
let pass = userPass.Parameters[0].Value;
return user, pass;
;
但是当我将两者缝合时,我得到 503 ERROR The request could not be compatible。 有谁知道我可能做错了什么?感谢您的帮助!
完整代码:
'use strict';
exports.handler = async (event, context, callback) =>
const ssm = new (require('aws-sdk/clients/ssm'))();
let userData = await ssm.getParameters(Names: ['website-user']).promise();
let userPass = await ssm.getParameters(Names: ['website-pass']).promise();
let user = userData.Parameters[0].Value;
let pass = userPass.Parameters[0].Value;
// Get request and request headers
const request = event.Records[0].cf.request;
const headers = request.headers;
// Construct the Basic Auth string
let authString = 'Basic ' + new Buffer(user + ':' + pass).toString('base64');
// Require Basic authentication
if (typeof headers.authorization == 'undefined' || headers.authorization[0].value != authString)
const body = 'Unauthorized';
const response =
status: '401',
statusDescription: 'Unauthorized',
body: body,
headers:
'www-authenticate': [key: 'WWW-Authenticate', value:'Basic']
,
;
callback(null, response);
// Continue request processing if authentication passed
callback(null, request);
;
【问题讨论】:
我认为你不能同时使用async
和callback
。如果您执行return response
或return request
会发生什么?
感谢您的共鸣!我尝试用return response
和return request
替换callback
,但我仍然遇到同样的错误。
@Jens 你把我推向了正确的方向,我修正了我的错误。我会发布解决方案作为答案。
【参考方案1】:
在阅读了有关 Promise 的内容后,我能够解决该错误。这是对我有用的解决方案:
'use strict';
var AWS = require('aws-sdk');
AWS.config.update( region: 'us-east-1' );
var ssm = new AWS.SSM();
function getParameter(param)
return new Promise(function (success, reject)
ssm.getParameter(param, function (err, data)
if (err)
reject(err);
else
success(data);
);
);
;
exports.handler = (event, context, callback) =>
let request = event.Records[0].cf.request;
let headers = request.headers;
let user = Name: 'user-path', WithDecryption: false;
let pass = Name: 'password-path', WithDecryption: false;
let authUser;
let authPass;
var promises = [];
promises.push(getParameter(user), getParameter(pass));
Promise.all(promises)
.then(function (result)
authUser = result[0].Parameter.Value;
authPass = result[1].Parameter.Value;
console.log(authUser);
console.log(authPass);
let authString = 'Basic ' + new Buffer(authUser + ':' + authPass).toString('base64');
if (typeof headers.authorization == 'undefined' || headers.authorization[0].value != authString)
const body = 'Unauthorized';
const response =
status: '401',
statusDescription: 'Unauthorized',
body: body,
headers:
'www-authenticate': [key: 'WWW-Authenticate', value:'Basic']
,
;
callback(null, response);
// Continue request processing if authentication passed
callback(null, request);
)
.catch(function (err)
console.log(err);
);
;
【讨论】:
以上是关于在 NodeJS 中使用 Lambda@Edge 对 CloudFront 进行基本 HTTP 身份验证的主要内容,如果未能解决你的问题,请参考以下文章
您是否可以使用除Javascript以外的语言使用Lambda @ Edge修改AWS CloudFront事件的URI?