You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS CDK部署React静态S3网站遇CloudFront 403访问拒绝问题

AWS CDK部署React静态网站出现403访问拒绝问题排查

问题描述

我正尝试通过AWS CDK将React应用部署为S3静态网站,已花费数小时排查但仍未定位问题。该应用在本地运行正常,但部署到S3后,访问CloudFront域名或自定义域名dev.mywebsite.com时均出现403访问拒绝错误。

CDK代码

from aws_cdk import (
    Stack,
    Tags,
    CfnOutput,
    aws_iam as iam,
    aws_s3 as s3,
    aws_cloudfront as cloudfront,
    aws_cloudfront_origins as cloudfront_origins,
    aws_route53 as r53,
    aws_route53_targets as route53_targets,
    aws_certificatemanager as acm,
    aws_s3_deployment as s3_deployment,
    RemovalPolicy,
)
from constructs import Construct


class CFS3StaticAppStack(Stack):

    def __init__(self, scope: Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # S3 Bucket for hosting the website
        site_bucket = s3.Bucket(
            self,
            "SiteBucket",
            bucket_name="s3-static-app",
            public_read_access=False,
            website_index_document="index.html",
            website_error_document="error.html",
            removal_policy=RemovalPolicy.DESTROY,
            block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
        )

        # CloudFront OAI
        oai = cloudfront.OriginAccessIdentity(self, "OAI")

        # Update the S3 bucket policy to allow access from CloudFront
        site_bucket.add_to_resource_policy(
            iam.PolicyStatement(
                actions=["s3:GetObject"],
                resources=[site_bucket.bucket_arn + "/*"],
                principals=[oai.grant_principal],
            )
        )

        # Add CORS configuration
        site_bucket.add_cors_rule(
            allowed_methods=[s3.HttpMethods.GET],
            allowed_origins=["*"],
            allowed_headers=["*"],
        )

        # CloudFront distribution for the website
        distribution = cloudfront.Distribution(
            self,
            "SiteDistribution",
            default_behavior=cloudfront.BehaviorOptions(
                origin=cloudfront_origins.S3Origin(
                    site_bucket, origin_access_identity=oai
                ),
                viewer_protocol_policy=cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
            ),
            default_root_object="index.html",
            error_responses=[
                cloudfront.ErrorResponse(
                    http_status=404,  # Error code
                    response_page_path="/error.html",
                    response_http_status=404,
                )
            ],
        )

        # Deploy the React application to S3
        s3_deployment.BucketDeployment(
            self,
            "ReactAppStaticWebsite",
            sources=[s3_deployment.Source.asset("./client_react/dist")],
            destination_bucket=site_bucket,
            distribution=distribution,
            distribution_paths=["/*"],
        )

        # Route53 alias record for the CloudFront distribution
        zone = r53.HostedZone.from_lookup(self, "Zone", domain_name="mywebsite.com")
        acm_cert = acm.Certificate.from_certificate_arn(
            self, "Cert", "arn:aws:acm:region:account:certificate/your-certificate-id"
        )

        # A record
        r53.ARecord(
            self,
            "SiteAliasRecord",
            zone=zone,
            target=r53.RecordTarget.from_alias(
                route53_targets.CloudFrontTarget(distribution)
            ),
            record_name="dev.mywebsite.com",
        )

        # Output CloudFront URL
        CfnOutput(
            self, "DistributionDomainName", value=distribution.distribution_domain_name
        )

        # Add tags to all resources in this stack
        Tags.of(self).add("Project", "Blah")
        Tags.of(self).add("Environment", "Blah")

错误信息

403 错误
请求无法被处理。
错误请求。目前无法连接到此应用或网站的服务器。可能是流量过大或配置错误。请稍后重试,或联系应用/网站所有者。
如果你通过CloudFront向客户提供内容,可以查看CloudFront文档获取故障排查步骤并避免此类错误。
由CloudFront生成
请求ID: xxxxxxxxxxxxxxxxxxxxx

排查与修复方案

1. 关联ACM证书到CloudFront分发

代码中已引用ACM证书,但未将其配置到CloudFront分发中。使用自定义域名时,CloudFront必须关联us-east-1区域的ACM证书,否则会导致请求被拒绝。

修改Distribution配置,添加证书和自定义域名参数:

distribution = cloudfront.Distribution(
    self,
    "SiteDistribution",
    default_behavior=cloudfront.BehaviorOptions(
        origin=cloudfront_origins.S3Origin(
            site_bucket, origin_access_identity=oai
        ),
        viewer_protocol_policy=cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
    ),
    default_root_object="index.html",
    error_responses=[
        cloudfront.ErrorResponse(
            http_status=404,
            response_page_path="/index.html",
            response_http_status=200,
        ),
        cloudfront.ErrorResponse(
            http_status=403,
            response_page_path="/index.html",
            response_http_status=200,
        )
    ],
    certificate=acm_cert,  # 关联证书
    domain_names=["dev.mywebsite.com"],  # 绑定自定义域名
)

2. 修复SPA路由错误处理

React单页应用直接访问子路由时,CloudFront会返回404,需将404/403错误重定向到index.html,由React路由处理页面跳转。修改上述代码中的error_responses配置即可。

3. 验证S3部署内容

确认./client_react/dist目录存在且构建产物完整,检查S3 Bucket中是否已同步index.html等核心文件。若部署未成功,CloudFront请求时会因找不到资源返回403。

4. 确认ACM证书区域

ACM证书必须部署在us-east-1区域,即使Bucket和CloudFront位于其他区域。检查引用的证书ARN对应的区域是否正确。

内容的提问来源于stack exchange,提问作者Pythoner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 04:50:54