如何基于AWS Lambda无服务器架构实现Spring Security ACL类细粒度授权
AWS无服务器方案实现实例级细粒度授权(博客评论场景)
核心设计思路
基于DynamoDB存储实例级ACL规则,通过Lambda函数处理权限配置与校验逻辑:
- 用DynamoDB复合键快速定位「特定博客」对应的「用户/角色权限规则」
- 博客所有者触发Lambda写入屏蔽规则(禁止指定用户/角色评论)
- 评论接口前置调用授权校验Lambda,判断当前用户是否被屏蔽
DynamoDB表结构设计
表名:ResourceACL
| 分区键(PK) | 排序键(SK) | 属性字段 | 说明 |
|---|---|---|---|
resourceType#resourceId | principalType#principalId | action | 控制的操作,如comment |
effect | 权限效果,如deny | ||
createdBy | 规则创建者(博客ID/用户ID) | ||
createdAt | 规则创建时间戳 |
示例数据:PK为
blog#123,SK为user#456,action为comment,effect为deny→ 表示禁止用户456评论博客123
Lambda函数实现(TypeScript)
1. 添加屏蔽规则(博客所有者调用)
该函数接收博客ID、目标主体类型(user/role)、主体ID,写入DynamoDB ACL规则:
import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb"; import { marshall } from "@aws-sdk/util-dynamodb"; const client = new DynamoDBClient({}); export const handler = async (event: any) => { const { blogId, principalType, principalId, createdBy } = JSON.parse(event.body); const params = { TableName: "ResourceACL", Item: marshall({ PK: `blog#${blogId}`, SK: `${principalType}#${principalId}`, action: "comment", effect: "deny", createdBy, createdAt: Date.now() }) }; try { await client.send(new PutItemCommand(params)); return { statusCode: 200, body: JSON.stringify({ message: "屏蔽规则已添加" }) }; } catch (error) { return { statusCode: 500, body: JSON.stringify({ error: "添加规则失败" }) }; } };
2. 评论权限校验(评论接口前置调用)
该函数接收当前用户ID、博客ID,查询DynamoDB判断是否存在禁止评论的规则:
import { DynamoDBClient, GetItemCommand } from "@aws-sdk/client-dynamodb"; import { marshall, unmarshall } from "@aws-sdk/util-dynamodb"; const client = new DynamoDBClient({}); export const handler = async (event: any) => { const { userId, blogId } = event.queryStringParameters; // 校验用户级屏蔽规则 const userParams = { TableName: "ResourceACL", Key: marshall({ PK: `blog#${blogId}`, SK: `user#${userId}` }) }; const userResult = await client.send(new GetItemCommand(userParams)); if (userResult.Item) { const rule = unmarshall(userResult.Item); if (rule.action === "comment" && rule.effect === "deny") { return { statusCode: 403, body: JSON.stringify({ message: "你已被禁止评论该博客" }) }; } } // 校验用户所属角色的屏蔽规则(假设角色信息来自Cognito授权上下文) const userRoles = event.requestContext.authorizer?.roles || []; for (const roleId of userRoles) { const roleParams = { TableName: "ResourceACL", Key: marshall({ PK: `blog#${blogId}`, SK: `role#${roleId}` }) }; const roleResult = await client.send(new GetItemCommand(roleParams)); if (roleResult.Item) { const rule = unmarshall(roleResult.Item); if (rule.action === "comment" && rule.effect === "deny") { return { statusCode: 403, body: JSON.stringify({ message: "你的角色已被禁止评论该博客" }) }; } } } // 无屏蔽规则,允许评论 return { statusCode: 200, body: JSON.stringify({ allowed: true }) }; };
前端调用示例(JavaScript)
博客所有者点击「屏蔽用户」按钮时,调用添加规则的API:
async function blockUserFromComment(blogId, userId, currentUserId) { try { const response = await fetch('https://<api-gateway-id>.execute-api.<region>.amazonaws.com/prod/add-block-rule', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${window.localStorage.getItem('idToken')}` }, body: JSON.stringify({ blogId, principalType: 'user', principalId: userId, createdBy: currentUserId }) }); const data = await response.json(); alert(data.message); } catch (error) { console.error('添加屏蔽规则失败:', error); } }
扩展优化建议
- 给DynamoDB添加全局二级索引,支持按用户/角色查询所有被屏蔽的博客
- 用AWS Cognito做身份认证,通过IAM策略限制只有博客所有者能调用添加规则的Lambda
- 批量校验角色权限时,改用
BatchGetItemCommand提升查询效率
内容的提问来源于stack exchange,提问作者NinjaDev786
相关产品推荐
相关产品推荐

