CloudFront Vue SPA配置Signed Cookies后出现Access Denied问题
背景与访问流程
- 我正在部署一个Vue单页应用(SPA),采用S3+CloudFront托管,通过Signed Cookies限制访问。该应用属于多租户平台,每个应用拥有独立的CloudFront域名。
- 完整访问流程:
- 用户点击开发应用的链接,主平台调用API验证用户的Cognito令牌,验证通过后重定向至
my-dev-app.cloudfront.net/auth - 该应用的CloudFront将
/auth路径作为行为模式,把请求路由至负责签发Signed Cookies的Lambda@Edge函数 - Lambda@Edge函数返回302重定向响应,同时设置Signed Cookies,引导用户进入开发应用首页
- 用户点击开发应用的链接,主平台调用API验证用户的Cognito令牌,验证通过后重定向至
当前问题
访问过程中始终出现access denied错误。CloudFront的默认行为指向S3源站,源站对应路径为prod/。
已确认以下信息:
- Lambda@Edge函数正常返回302响应,浏览器中可以看到已设置好的三个Signed Cookies(CloudFront-Policy、CloudFront-Signature、CloudFront-Key-Pair-Id)
- 若关闭CloudFront的Signed Cookies限制(开放公网访问),应用可以正常运行
Lambda@Edge函数代码
'use strict'; const crypto = require('crypto'); // === CONFIG === const CF_KEY_PAIR_ID = 'ABCDEF1234'; const CF_PRIVATE_KEY = ` -----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY----- `; exports.handler = async (event) => { try { const request = event.Records[0].cf.request; const host = request.headers.host[0].value; const expires = Math.floor(Date.now() / 1000) + 600; const policy = JSON.stringify({ Statement: [{ Resource: `https://${host}/*`, Condition: { DateLessThan: { 'AWS:EpochTime': expires } } }] }); const signature = crypto .createSign('RSA-SHA256') .update(policy) .sign(CF_PRIVATE_KEY, 'base64'); return { status: '302', statusDescription: 'Found', headers: { 'location': [{ key: 'Location', value: '/' }], 'set-cookie': [ { key: 'Set-Cookie', value: cookie('CloudFront-Policy', toBase64Url(policy)) }, { key: 'Set-Cookie', value: cookie('CloudFront-Signature', toBase64Url(signature)) }, { key: 'Set-Cookie', value: cookie('CloudFront-Key-Pair-Id', CF_KEY_PAIR_ID) } ] } }; } catch (e) { return { status: '500', statusDescription: 'Internal Server Error', body: 'Internal Server Error' }; } }; // ===== Helpers ===== function cookie(name, value) { return `${name}=${value}; Path=/; Secure; HttpOnly; SameSite=Lax`; } function base64urlToBuffer(str) { return Buffer.from(str.replace(/-/g, '+').replace(/_/g, '/'), 'base64'); } function toBase64Url(str) { return Buffer.from(str) .toString('base64') .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); }
内容的提问来源于stack exchange,提问作者Yolo_chicken
相关产品推荐
相关产品推荐

