使用 AWS 和 S3 存储桶对静态站点进行基本用户身份验证

Posted

技术标签:

【中文标题】使用 AWS 和 S3 存储桶对静态站点进行基本用户身份验证【英文标题】:Basic User Authentication for Static Site using AWS & S3 Bucket 【发布时间】:2019-09-16 09:40:21 【问题描述】:

我希望将基本用户身份验证添加到我将在 AWS 上拥有的静态站点,以便只有具有我将提供给这些用户的正确用户名 + 密码的用户才能访问该站点。我找到了 s3auth,它似​​乎正是我想要的,但是,我想知道是否需要以某种方式为 index.html 以外的页面设置授权。例如,我有 3 个页面索引、about 和 contact.html,但没有为 about.html 设置身份验证是什么阻止了个人通过 www.mywebsite.com/about.html 直接访问该站点?我更需要澄清或任何人可以提供的任何资源来解释这一点!

感谢您的帮助!

【问题讨论】:

我没有使用 s3auth,但它看起来是一个位于整个存储桶前面的网关。您无需担心单个对象的权限。 @bwest 感谢您的回复。无论如何,您是否有另一种解决方案可以完成同样的事情?我读到了在存储桶前面设置 Cloudfront Distribution(不知何故?还是新的,所以不确定如何),然后使用 lambda 函数来模拟 http 基本身份验证?或多或少为我和其他人可以通过用户名和密码访问的测试环境寻找相对安全的东西。 【参考方案1】:

这是 Lambda@Edge 的完美用途。

由于您将静态站点托管在 S3 上,因此您可以使用 AWS 的内容分发网络 CloudFront 轻松且非常经济地(几分钱)为您的站点添加一些非常棒的功能,从而为您的用户提供站点服务。您可以了解如何使用 CloudFront(包括 100% 免费 SSL)here 在 S3 上托管您的网站。

在部署您的 CloudFront 分配时,您将有一些时间来设置您将用于执行基本用户身份验证的 Lambda。如果这是您第一次创建 Lambda 或创建用于使用 @Edge 的 Lambda,则该过程会感觉非常复杂,但是如果您按照下面我的分步说明进行操作,您将执行无限的无服务器基本身份验证在不到 10 分钟的时间内进行扩展。我将为此使用 us-east-1,重要的是要知道,如果您使用的是 Lambda@Edge,您应该在 us-east-1 中编写您的函数,并且当它们与您的 CloudFront 分配相关联时,它们'将自动在全球范围内复制。开始吧……

    前往 AWS 控制台中的 Lambda,然后单击“Create Function” 从头开始创建您的 Lambda 并为其命名 将运行时设置为 Node.js 8.10 通过选择“选择或创建执行角色”为您的 Lambda 授予一些权限 为角色命名 从策略模板中选择“基本 Lambda@Edge 权限(用于 CloudFront 触发器)” 点击“创建函数” 创建 Lambda 后,将以下代码粘贴到 Function Code 部分的 index.js 文件中 - 您可以通过更改 authUser 和 authPass 变量来更新要使用的用户名和密码:李>
'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);
;

    点击右上角的“保存”。 现在您的 Lambda 已保存,可以附加到您的 CloudFront 分配。在上方菜单中,选择操作 -> 部署到 Lambda@Edge。 在出现的模式中,从下拉菜单中选择您之前创建的 CloudFront 分配,将缓存行为保留为 *,并将 CloudFront 事件更改为“查看器请求”,最后选择/勾选“包含正文” .选择/勾选 Confirm deploy to Lambda@Edge 并单击“Deploy”。

现在你等着。跨所有区域和边缘站点复制您的 Lambda@Edge 需要几分钟 (15-20)。转到 CloudFront 以监控您的函数的部署。当您的 CloudFront 分发状态显示“已部署”时,您的 Lambda@Edge 函数就可以使用了。

【讨论】:

你太棒了!感谢您一步一步深入。非常感谢。 我的荣幸;很高兴它有帮助。 callback(null, response); 应该以return 开头,否则在这种情况下此代码将调用回调两次,这可能难以检测但仍会产生负面影响。我希望节点进程被杀死并透明地重新生成,从而导致处理时间超过必要的时间,介于热启动和冷启动之间,以便下一次调用命中同一个容器......如果不是容器破坏......由于可能发生的异常(但可能不会被记录,或者可能在下一次调用期间抛出)。 @hephalump 只是想让您知道您的解决方案完美运行,这正是我想要的。 如果您在第 10 步没有看到“部署到 Lambda@Edge”选项,请确保您位于 us-east-1 区域。 see aws docs【参考方案2】:

部署 Lambda@edge 很难通过控制台进行复制。所以我创建了 CDK 堆栈,您只需添加自己的凭据和域名并部署即可。

https://github.com/apoorvmote/cdk-examples/tree/master/password-protect-s3-static-site

我已经用 Node12.x 测试了以下函数

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

const request = event.Records[0].cf.request

const headers = request.headers

const user = 'my-username'

const password = 'my-password'

const authString = 'Basic ' + Buffer.from(user + ':' + password).toString('base64')

if (typeof headers.authorization === 'undefined' || headers.authorization[0].value !== authString) 

    const response = 
        status: '401',
        statusDescription: 'Unauthorized',
        body: 'Unauthorized',
        headers: 
            'www-authenticate': [key: 'WWW-Authenticate', value:'Basic']
        
    

    callback(null, response)


callback(null, request)

【讨论】:

以上是关于使用 AWS 和 S3 存储桶对静态站点进行基本用户身份验证的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 S3 在 aws 中设置静态站点 - 是不是有视觉指南?

尝试访问管理字体文件时,Django 在 AWS S3 中托管静态文件导致 CORS 错误

使用 AWS Elastic Beanstalk 进行部署时,是不是应该将静态文件存储在单独的 S3 中?

具有 HTTPS 和仅限 *** 访问的 AWS S3 静态站点

AWS 静态网站 + 云端签名 cookie

AWS S3 静态站点 CORS jquery ajax POST 到 API Gateway