使用身份验证重定向在 AWS S3 上托管 Angular SPA

Hosting Angular SPA on AWS S3 with Authentication Redirects

我们的 SPA 是用 Angular(即 Angular2,Angular4。不是 AngularJS)编写的,并使用 OAuth2 针对 Azure AD 进行身份验证。我们正在使用 OIDC library 来处理身份验证。

该应用程序托管在配置为服务于静态网站的 AWS S3 存储桶中。为了便于讨论,我们假设 URL 是 myapp.example.com.

当用户单击登录按钮时,他们将被重定向到 Microsoft 页面以处理身份验证。到目前为止,一切都很好。一旦他们通过身份验证,他们将被重定向回 myapp.example.com/login

但是我的名为 login 的 S3 存储桶中没有工件。 login 路由由 Angular 路由器处理,并在我的应用程序中调用一个组件。当我在我的本地机器上 运行ning 时,这一切在开发中都运行良好。但是当我 运行 S3 中托管的版本时,重定向回 myapp.example.com/login 失败并出现 404 错误。

我了解错误的原因 - 我的 S3 存储桶中没有名为 login 的项目。但我想这对我的应用程序中的几乎所有 link 来说都是一个问题。例如,如果我与另一个用户共享 link 到 myapp.example.com/objects/1234,我想他们也会收到 404。

所以问题是,我需要做什么才能在 AWS 中正​​确托管此 SPA,以便重定向和其他 link 正常工作?

在S3 前面配置AWS CloudFront 并为CloudFront 做域映射(使用CNAME)。然后使用 AWS Edge Lambda,您可以重写 URL for /login 以指向 index.html.

这也将为 /login 路径加载 index.html 并在重定向发生后从客户端触发 Angular 中的路由。

这是一个老话题,但我是在做类似项目时发现的。使用 Lambda 既不理想也没有必要,因此我将其作为更新答案包括在内,以帮助其他人搜索此问题。

这个问题实际上是在 Knowledge Center.

Note: If a requested object doesn’t exist in the bucket and the requester doesn’t have s3:ListBucket access, then the requester receives an HTTP 403 Access Denied error rather than an HTTP 404 error. If this is the case, you must resolve the issue related to the missing object to address the HTTP 403 error.

你只需要做两件事。

  1. 添加一个 custom error page 到 CloudFront
  2. 更新您的存储桶策略

1) 创建分配后,单击分配的 ID 返回设置。您应该会看到多个选项卡,其中之一是 Error Pages。点击错误页面,然后点击创建自定义错误响应。从这里开始,您需要为 404 处理设置重定向以确保您的 SPA 正常工作

设置:

  • HTTP 错误代码404:未找到
  • 错误缓存最小 TTL(秒) 为您想要的任何值,默认工作。这是你的缓存。
  • 自定义错误响应
  • 响应页面路径/index.html
  • HTTP 响应代码200:OK

2) 我们从知识中心了解到,如果该对象不存在,并且您没有 s3:ListBucket,您将获得 403 而不是 404 . 测试时我们注意到您实际上得到了 NoSuchKey。好的,知识中心给了我们解决方案,我们只需要更新存储桶策略即可。

如果设置正确,CloudFront 源访问身份应该已经设置为存储桶策略。它看起来像:

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ORIGIN_ACCESS_ID"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::BUCKET_NAME/*"
        }
    ]
}

现在您只需要添加新的参数。同样重要的是要注意这个新参数使用不同的资源。所以新政策现在应该类似于:

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "AllowCloudFrontOriginAccess",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ORIGIN_ACCESS_ID"
            },
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::BUCKET_NAME",
                "arn:aws:s3:::BUCKET_NAME/*"
            ]
        }
    ]
}

您的 SPA 现在应该可以正常工作,没有任何 Lambda 攻击。

参考:Guide I wrote while working on a similar project