S3预签名URL失效机制设计咨询(含Cognito用户池场景)
Great question—let’s break this down with practical, scalable solutions that fit your constraints, since creating individual IAM accounts for every Cognito user is absolutely not a feasible, scalable approach (it’d be a management nightmare).
First, to confirm your initial note: AWS doesn’t have an API to invalidate existing pre-signed URLs directly. So we need to build workarounds that align with your goals of simplicity, low cost, and efficiency.
1. Optimizing Your Random Token Directory Idea (Avoid Duplicate Files)
Your approach of using a long, secure token as a directory prefix (e.g., /{token}/file.txt) solves the isolation problem, but the file duplication is a valid pain point. The good news is you don’t have to copy files at all—here’s how to fix it:
- Use CloudFront + Edge Logic for Path Rewriting: You mentioned thinking CloudFront couldn’t map different URLs to the same S3 file, but that’s not true. With Lambda@Edge (or the lighter, cheaper CloudFront Functions), you can rewrite the request path on the fly. For example:
- A user requests
https://your-cf-domain/abc123-token/file.txt - The edge function extracts the token, checks a DynamoDB table to confirm it’s valid (not revoked, not expired)
- If valid, rewrite the path to point to the original S3 object (e.g.,
/original-files/file.txt) and forward the request - If invalid, return a 403 Forbidden
- A user requests
This way, you only store one copy of the file, and invalidation is as simple as marking the token as revoked in DynamoDB. No more duplicate storage.
If you still prefer the "minimal overhead" route and your files are small, your original duplicate-file approach is totally acceptable—S3 storage costs are negligible for small files, and you can invalidate access by deleting the token-specific file or just stopping the generation of new pre-signed URLs for that token (existing ones will expire based on your pre-sign TTL).
2. Making the Per-Request Lambda Approach Efficient
You’re right to worry about Lambda overhead, but this can be optimized to be both fast and low-cost:
- Cache Validation Results: Use DynamoDB with TTL to cache token validity, or add an ElastiCache layer for frequent requests—this cuts down on repeated database lookups.
- Lambda@Edge + CloudFront Caching: Deploy your validation logic to CloudFront’s edge locations (Lambda@Edge Viewer Request trigger). This means requests are processed close to the user (low latency), and CloudFront can cache successful, valid requests to reduce Lambda calls.
- Cost is Minimal: Lambda’s free tier covers millions of calls, and Lambda@Edge pricing is competitive. For most workloads, this will be cheaper than storing duplicate large files.
3. The Most Scalable Hybrid Solution
For large Cognito user pools, this balance of simplicity and scalability works best:
- Use Cognito Identity Pools: Generate temporary IAM credentials for each Cognito user (no need for individual IAM accounts). These credentials can be scoped to specific prefixes or resources if needed.
- Generate Token-Bound Pre-Signed URLs: Include a unique, revocable token in the pre-signed URL (stored in DynamoDB with user ID, file ID, and validity status).
- Edge Validation with CloudFront: Use Lambda@Edge to check the token’s validity before forwarding to S3. If the token is revoked, block the request immediately.
- Instant Invalidation: To revoke access, just update the token’s status in DynamoDB—no need to touch S3 files or wait for pre-signed URLs to expire.
This approach gives you instant invalidation, no duplicate storage, and scales seamlessly with thousands or millions of Cognito users.
Quick Note on CloudFront Path Mapping
To clarify your earlier confusion: CloudFront absolutely supports mapping different URLs/parameters to the same S3 object. The key is using edge functions to rewrite paths and validate tokens before hitting the origin. CloudFront Functions are perfect for simple path rewrites, while Lambda@Edge handles more complex logic like database lookups.
内容的提问来源于stack exchange,提问作者Vitaly Zdanevich

