news 2026/5/1 6:01:03

跨组织/跨租户权限怎么设计:隔离/共享/委托(附SaaS权限模板)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
跨组织/跨租户权限怎么设计:隔离/共享/委托(附SaaS权限模板)

前言

多租户是SaaS系统的核心特性。很多SaaS系统的数据泄露都是因为租户隔离没做好。这篇给你多租户权限的3种策略+完整设计方法。

一、3种多租户策略

策略特点适用场景优点缺点
完全隔离每个租户独立数据库高安全要求安全性高成本高
共享隔离共享数据库,tenant_id隔离通用SaaS成本低需严格校验
混合模式核心数据隔离,其他共享平衡安全与成本灵活复杂度高

二、共享隔离模式(推荐)

核心原则

  • 所有数据表必须有tenant_id字段
  • 所有查询必须带WHERE tenant_id = 当前租户ID
  • 跨租户访问返回403

实现步骤

步骤1:数据表设计

所有业务表必须包含tenant_id字段,并建立索引。

订单表(orders)示例: CREATE TABLE orders ( id BIGINT PRIMARY KEY AUTO_INCREMENT, tenant_id BIGINT NOT NULL COMMENT '租户ID', user_id BIGINT NOT NULL COMMENT '用户ID', order_no VARCHAR(32) NOT NULL COMMENT '订单号', amount DECIMAL(10,2) NOT NULL COMMENT '订单金额', status VARCHAR(20) NOT NULL COMMENT '订单状态', created_at DATETIME NOT NULL, INDEX idx_tenant_id (tenant_id), INDEX idx_tenant_user (tenant_id, user_id) ) COMMENT='订单表'; 注意: - tenant_id必须NOT NULL - 在tenant_id上建立索引,提高查询性能 - 联合索引(tenant_id, user_id)支持按租户和用户查询
步骤2:租户ID获取

从用户登录信息中获取tenant_id,不能从请求参数中获取。

伪代码示例: // 从JWT Token中获取租户ID function getTenantId(request) { const token = request.headers.authorization; const decoded = jwt.decode(token); return decoded.tenant_id; // 从token中获取,不能从参数获取 } // 从Session中获取租户ID function getTenantIdFromSession(request) { return request.session.user.tenant_id; // 从session中获取 }
步骤3:查询自动过滤

在数据访问层统一添加tenant_id过滤条件。

伪代码示例: // 数据访问层统一处理 function getOrders(user, filters) { let query = "SELECT * FROM orders"; let where = []; // 自动添加tenant_id过滤 where.push("tenant_id = " + user.tenant_id); // 添加其他过滤条件 if (filters.status) { where.push("status = '" + filters.status + "'"); } if (where.length > 0) { query += " WHERE " + where.join(" AND "); } return executeQuery(query); } // 平台管理员特殊处理 function getOrdersForAdmin(admin, filters) { let query = "SELECT * FROM orders"; let where = []; // 平台管理员不添加tenant_id过滤,但可以指定租户 if (filters.tenant_id) { where.push("tenant_id = " + filters.tenant_id); } if (where.length > 0) { query += " WHERE " + where.join(" AND "); } return executeQuery(query); }
步骤4:跨租户访问校验

在接口层校验数据归属,防止跨租户访问。

伪代码示例: // 接口层校验 app.get('/api/orders/:id', async (req, res) => { const order = await getOrderById(req.params.id); const userTenantId = req.user.tenant_id; // 校验租户归属 if (order.tenant_id !== userTenantId && req.use
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 13:58:25

老年关怀产品设计:用GLM-TTS降低数字鸿沟影响

老年关怀产品设计:用GLM-TTS降低数字鸿沟影响 在社区健康站的一次调研中,一位78岁的老人反复按下智能血压仪的语音播报键,却始终皱着眉头:“它说‘请服用硝苯地平’,可我听成了‘心崩地皮’,吓一跳。”旁边…

作者头像 李华
网站建设 2026/4/19 1:17:25

GitHub Issues维护:及时响应用户提交的bug反馈

GitHub Issues维护:及时响应用户提交的bug反馈 在开源社区,一个项目的生命周期往往不只取决于代码质量,更在于它如何与用户互动。尤其是像 GLM-TTS 这样面向实际应用场景的语音合成系统,每一次用户提交的 Issue 都可能揭示出真实使…

作者头像 李华
网站建设 2026/4/30 12:10:48

虚拟数字人驱动:结合GLM-TTS与Live2D实现语音动画同步

虚拟数字人驱动:结合GLM-TTS与Live2D实现语音动画同步 在直播弹幕中挥手打招呼的虚拟主播、用温柔语调讲解知识点的AI教师、在客服窗口耐心答疑的卡通助手——这些不再是科幻电影中的桥段,而是正在走进现实的人机交互新形态。但你有没有注意到&#xff0…

作者头像 李华
网站建设 2026/5/1 4:02:54

健身房教练语音:个性化指导运动节奏与动作

健身房教练语音:个性化指导运动节奏与动作 在一间现代智能健身房里,一面看似普通的镜子突然响起声音:“挺胸,核心收紧——很好,保持这个姿势!”语气坚定却不失鼓励,音色熟悉得就像你每周预约的那…

作者头像 李华
网站建设 2026/4/30 21:36:29

火车站检票口提示音:动态更新列车延误通知

火车站检票口提示音:动态更新列车延误通知 在高峰时段的火车站,广播里传来机械而冰冷的声音:“G1234次列车晚点。”没有解释、没有语气变化,甚至“G”被读成了“鸡”。乘客皱眉、焦躁,服务台前排起长队。这样的场景并不…

作者头像 李华