资讯动态

授权与访问控制:从RBAC到ABAC,深入解析权限设计与落地实践

发布时间:2026/10/14 22:29:42 来源:尧图企业网站定制
授权与访问控制这几个字在安全圈里被念叨了十几年但真把它做明白的系统我这些年做代码审计和渗透测试时见到的真不算多。最常见的情况是平台账号体系做得挺完善密码策略、短信验证、人脸识别全上了结果到了接口层改个ID参数就能翻出别人的订单典型的“认证满分、授权零分”。授权与访问控制本质要解决的就是“谁能在什么条件下、对什么资源、做什么操作”它比认证更隐蔽也更容易被人忽略但恰恰是内部数据泄露的第一大原因。这篇文章写给正在设计权限模块的后端开发、做安全评审的工程师也写给每个想搞清楚系统权限逻辑的运维和测试同学我会把模型选型、落地步骤、常见坑点一次讲透所有内容基本都来自实际项目中真刀真枪遇到的问题。1. 先把概念对齐认证、授权与访问控制到底是什么关系1.1 一次印象深刻的越权事故之前帮某公司做安全评估他们的后台管理系统有个下载报表的功能。开发同学把登录校验做得很足每个请求都会验证TokenToken过期还会自动跳转重新登录。我拿到一个普通运营的账号登录后习惯性地把请求里的订单编号改了改从/api/report/download?id10086改成id10085结果直接下载到了上一家客户的合同报表。整个过程没触发任何告警因为系统只校验了“你是不是登录用户”完全不校验“你有没有下载这份报表的权限”。那次之后我跟他们复盘问题根源就一句话开发把认证当成了安全认为“验证了身份”就等于“允许操作”。这是非常普遍的误解也是越权漏洞之所以成为高危漏洞的原因。授权和访问控制管的是更细一层的秩序它要求系统在确认你是谁之后还得查一遍“你有没有资格干这件事”。1.2 认证与授权两个经常被混为一谈的环节认证解决的是身份问题英文叫Authentication核心是“证明你是你”。密码、验证码、指纹、人脸识别、证书本质上都是在做这件事。认证的结果通常是颁发一个凭证比如Session ID、Token或者票据证明这个人已经通过了身份核验。授权解决的是权限问题英文叫Authorization核心是“你被允许做什么”。它建立在认证之上但逻辑完全独立。一个用户即使通过了认证也不代表他能访问所有功能、所有数据。举个生活中的例子小区门禁刷脸是认证刷完脸能不能进地下车库、能不能打开物业办公室的门这是授权。门禁系统告诉你“我认识你”但“你能去哪儿”是另一套规则在管。访问控制则是授权的具体执行机制它把授权规则落实到每一次请求上。所以完整的链路是认证确认身份 → 授权查询权限规则 → 访问控制引擎执行拦截或放行。三个环节少一个安全体系都会出问题。1.3 访问控制的三个核心角色主体、客体、权限规则做访问控制设计之前必须把三个基础概念刻在脑子里。主体Subject——发起访问的一方可以是用户、用户组、服务账号甚至是另一个系统。在微服务架构里服务之间互相调用也需要访问控制此时主体就是某个服务实例。客体Object——被访问的资源可以是页面、接口、文件、数据库某张表里的某一行数据也可以是某项操作按钮。客体的粒度决定权限的精细程度。权限规则Policy——描述主体对客体能做什么、不能做什么的约束。最简单的规则是“允许或拒绝”复杂一点的会加上时间、地点、设备、IP等条件。我在实际项目里发现一个规律凡是权限系统做得混乱的基本上都是对这三样东西的界定不清晰。要么主体混杂了用户和角色要么客体粒度一会儿是页面、一会儿是按钮、一会儿又是字段这样的规则表写出来一定是一团乱麻。所以落地之前先把这三个名词在团队里对齐后面才好开展工作。2. 四种访问控制模型怎么选才不会后期返工2.1 DAC与ACL最直观但容易失控的“门牌号”访问控制模型不是随便挑一个就完事它直接影响系统未来的扩展性。先说最传统的自主访问控制DAC它的核心思想是“资源的所有者说了算”。谁创建了文件谁就有权决定谁能访问。Linux文件系统的rwx权限就是典型的DAC你可以用chmod命令把某个目录开放给其他用户。DAC落到具体实现就是访问控制列表ACL直接在资源上挂一个列表记录哪些主体能做什么操作。ACL简单直观适合文件存储、小型工具类系统。但它有两个硬伤一是权限分散在每个资源上很难统一查看用户总共拥有哪些权限二是一旦文件多、用户多ACL条目会爆炸管理成本直线上升。我记得有个团队用ACL管理内部文档库开始只有几十号人每人建几个目录ACL还能应付。后来人数涨到几百员工调动频繁整个权限表变得乱七八糟谁也说不清某个离职账号到底还能访问哪些目录。这就是DAC模型在规模化之后的典型失控状态。2.2 RBAC企业级系统的默认答案但要小心“角色爆炸”基于角色的访问控制RBAC是目前企业级系统的主流答案核心思路是引入“角色”这个中间层。管理员不再直接给用户分配权限而是给角色分配权限再把用户加入角色。用户“继承”了角色的所有权限。这个思路的好处很明显权限管理抽象成了“管角色”而不是“管人”。新人入职加入销售角色就有了销售需要的全部权限转岗移出旧角色、加入新角色权限就跟着变了。这也是最小权限原则的最好载体只要角色拆分合理用户天然只拥有工作需要的权限。但RBAC也有自己的坑最大的坑是角色爆炸。有些团队把角色设计得特别细比如“华东区销售经理”“华东区销售专员”“华北区销售经理”当区域、部门、职级、业务线几个维度叠加在一起角色数量分分钟上百。角色一多权限规则就难以维护最后演变成给用户直接挂权限RBAC名存实亡。解决角色爆炸的办法是引入“用户组 角色”两层结构用用户组解决“人”的维度用角色解决“权限”的维度或者干脆考虑下一节的ABAC。2.3 ABAC当业务需要动态判断时属性才是真理基于属性的访问控制ABAC把决策依据从“身份”扩大到“属性”。这里的属性包括主体的属性部门、职级、城市、客体的属性数据归属人、密级、创建时间、环境的属性时间、IP、设备状态。规则变成类似“当请求者的部门等于资源的归属部门且请求时间在工作时间内时允许访问”这样的条件表达式。ABAC的优点是灵活性极强特别适合权限规则随业务动态变化的场景。比如某个财务系统要求“普通会计只能查看自己负责公司的账目”在RBAC里你得为每一家公司都建角色而ABAC只需要一条规则让“公司归属字段”等于“当前登录用户负责的公司列表”。再比如访客系统里“外部访客只能在上午九点到下午五点访问研发楼层”这种时间维度的控制RBAC做起来很别扭ABAC天然支持。代价是复杂度。ABAC需要设计属性体系需要规则引擎来解析策略表达式团队没有一定抽象能力很容易把规则写得又乱又难排查。我的建议是能用RBAC说清楚的就别上ABAC当规则里出现大量“如果…且…则…”句式时再考虑引入ABAC做补充。2.4 模型选型对照表与我的个人建议模型核心逻辑优点缺点典型场景DAC/ACL资源所有者授权简单直接实现成本低规模化后管理混乱权限分散文件系统、小型工具RBAC用户通过角色获得权限管理集中符合最小权限原则易审计角色数量易膨胀动态条件表达弱企业内部系统、后台管理ABAC基于主体/客体/环境属性动态决策灵活强支持复杂策略实现复杂需要规则引擎排查难度高云平台、跨部门协作系统混合模型RBAC为主ABAC补充兼顾可维护性与灵活性设计难度高两套逻辑需协同大型中大型系统我个人在乙方评估和甲方建设两类项目里反复比较后倾向一个默认组合主体权限用RBAC管理特殊场景用ABAC规则做策略覆盖。先把用户、角色、权限这三级结构搭稳保证日常运维有章可循再在个别需要动态判断的接口上叠加属性条件比如数据权限范围、时间限制。这种混合模式既避免了RBAC的角色爆炸也回避了ABAC全面铺开带来的维护痛苦。3. 权限落地实操从梳理资源到角色设计3.1 第一步盘点资源明确授权粒度权限设计最怕上来就写代码。我见过太多项目开发凭感觉建了几张角色表菜单一把梭接口权限和页面权限混在一起最后自己都说不清角色A和角色B到底差在哪儿。正确做法是先把资源盘清楚系统里有哪些页面、哪些接口、哪些数据对象需要保护。盘点时可以画一张简单的清单资源名称、类型页面/接口/按钮/数据、访问方式、归属模块、是否需要数据权限过滤。这张清单同时也是未来权限目录的第一版草稿。授权粒度方面我建议遵循“越核心越细”的原则普通查询列表页面做到接口级控制就够了但涉及资金操作、批量导出、删除数据这类敏感功能一定要细到按钮级甚至要再做一层数据范围校验。有个误区值得提醒很多团队把资源粒度全部按按钮做菜单权限、页面权限、按钮权限全部拆开。看起来控制得很精细实际上配置成本极高一个角色配下来要点几十个checkbox用户一多就烦了。更合理的做法是分层控制菜单和页面控制“能不能进”接口控制“能不能调”数据范围控制“能看哪些”每个层级关注不同的问题不要混在一起。3.2 第二步设计角色守住最小权限与职责分离角色设计是RBAC落地最关键也最容易被忽略的一环。很多开发直接把“职位名称”当角色用其实这里有个隐含误区职位是行政概念角色是权限集合概念。一个“项目经理”在不同系统里权限可能完全不同在项目管理工具里他是资源分配者在财务系统里他可能只有查看权限。设计角色要遵循三个原则。首先是最小权限原则每个角色只拥有完成工作所必需的最小权限集合多给一条权限就是多一分风险。其次是职责分离原则互斥操作必须拆到不同角色里比如“发起付款申请的人不能是审批付款的人”否则就存在内部舞弊可能。第三方系统对接账号同样要遵循这一点开发环境、测试环境、生产环境的账号权限必须分开。第三是角色可解释性每个角色必须有清晰的名称、描述和权限清单写清楚“为什么需要这些权限”。我见过有公司角色名叫“超级管理员2”跟“超级管理员1”权限大差不差这种角色名后人维护起来极度痛苦。如果权限集合长期没人维护定期review发现不少角色看似不同、权限重叠严重该合并就合并。3.3 第三步权限评审让业务方参与而不是开发自嗨权限规则如果只由开发或产品单方面定义往往会偏离实际业务流程。最典型的案例一个内容审核平台开发和产品把“审核人员”角色设置了删除权限理由是“审核不通过的内容需要删除”。但业务方的流程里问题内容只需要标记“驳回”删除是运营主管才能执行的操作。结果上线第一天审核员不小心删了一条重要投诉记录数据恢复花了两天。我的建议是角色和权限定义完成后必须拉上业务方负责人做一次评审让每个角色在业务流程里实际“走”一遍用这个角色登录后能不能完成他的本职工作能不能看到不该看的数据能不能执行不该执行的操作这样就能提前拦截掉“权限给多”或“权限给少”两种问题。评审还有一个作用是让业务方为权限合理性背书。权限设计不再是开发单方面的技术方案而是经过业务确认的管理约定。后续审计时如果有人质疑某角色权限过大可以直接追溯评审记录和责任人来回应省掉很多扯皮的麻烦。3.4 临时授权与会话过期两个容易漏掉的细节第两个容易漏掉的细节是临时授权和会话过期。临时授权在运维场景特别常见某晚上线变更需要某个工程师临时拥有生产环境的配置权限或者财务月底需要临时开放导出功能给财务专员。如果你的系统只支持固定角色分配遇到这种情况只能临时把用户加入高权限角色再手动移除。但人都有忘性权限加上了就忘了回收账号权限像滚雪球一样越滚越大。比较好的做法是设计“临时授权”机制授权时指定截止时间时间一到权限自动失效或者走审批流临时权限到期前系统自动提醒。做一个带有效期的权限中间表技术上非常容易却能在很大程度上防止权限膨胀。会话过期这块同样要重视。权限的判断依赖会话但会话的有效期一旦没跟权限变更联动就会出现“用户已从角色移除但Token还没过期依然能调用接口”的漏洞。设计时要让Token或会话不仅包含身份信息还要在权限变更时触发会话失效或强制重新校验特别是用户被移出角色、账号被禁用这类高风险操作必须立即使所有已签发凭证失效。4. 访问控制的实现层网关拦截、后端鉴权与越权防御4.1 统一在网关做鉴权别把权限散落在每个服务里很多系统一开始是单体应用权限判断写在一个中间件里代码量不大倒还好。后来业务拆成微服务每个服务各写一套权限判断问题就来了有些服务判断了角色有些服务忘了判断有些服务用自己维护的权限表A服务更新了账号状态B服务的缓存还保留着旧权限。权限规则散落各处安全机制变成“靠自觉”。解决办法是“统一鉴权入口”。在API网关层集中做认证和初步授权把身份解析、黑白名单、角色校验、敏感接口访问控制集中在网关里完成后端的每个服务只做数据层面的访问校验不关心“用户是谁”只关心“传进来的上下文里带着什么授权信息”。这样权限变更只需要改网关或权限中心不用动各服务代码。但统一入口也有一个副作用网关成了性能瓶颈和单点故障。为了减小风险网关层的权限校验尽量用缓存、本地规则库不要把每个请求都回源查询权限中心。权限中心的策略变更再通过消息或定时刷新同步到各节点做到最终一致。4.2 后端鉴权的三种常见实现方式实现层最核心的问题是“每次请求如何知道当前用户是谁、有什么权限”。常见方案有三类各有适用场景第一种是传统Session方案。用户登录后服务端保存Session浏览器保存Cookie。后端读取Session中的用户ID再查权限表判断是否有权限。优点是实现简单配合Redis可以支持多实例部署缺点是移动端体验略差Cookie管理麻烦。第二种是Token方案特别以JWT为代表。用户登录后服务端签发一个带签名的Token里面包含用户ID、角色、过期时间等信息。后端验签后直接从Token里取权限字段不需要查库分布式系统里特别方便。缺点是Token一旦签发在过期前很难撤销所以权限变化不能依赖Token里的旧数据必须结合版本号或黑名单。第三种是独立的权限中心方案。所有请求通过网关到达权限中心权限中心动态从规则库计算是否有权限再把决策结果返回给调用方。这种方式最灵活也最适合ABAC但链路长、延迟高一般只有对性能要求不高的大型系统采用。不管采用哪种方案我都建议把“身份识别”和“权限获取”解耦身份识别只负责确认用户是谁权限获取则每次请求时动态取得。别把权限直接写到Token里长期不变否则权限回收一定滞后。4.3 水平越权与垂直越权的防御要点越权漏洞分为两种。水平越权指普通用户可以访问同级别其他用户的数据比如之前提到的改订单编号看别人订单垂直越权指低权限用户访问高权限功能比如普通员工调用管理员接口篡改用户配置。水平越权的核心防御是数据归属校验处理涉及具体资源的请求时不能只验证“用户已登录”必须验证“这个资源属于当前请求者”。开发时就得明确资源数据里必须有一个owner字段在数据访问层强制叠加条件而不是让业务代码自己判断。比如查询订单时SQL必须带上WHERE user_id 当前用户ID而不是先查出来再在内存里比一遍——内存过滤照样有高效绕过风险。垂直越权的核心防御有两种。一是接口级角色校验管理员接口统一标注需要特定角色网关统一拦截。二是“默认拒绝”策略宁可不给权限导致用户投诉也不要默认放行。很多垂直越权都是因为开发新写一个接口时忘了加“管理员”角色校验而框架没有默认拒绝机制导致所有登录用户都可调用。我这儿有个实操习惯每个涉敏接口导出、批量操作、删除、资金操作都要在方法或路由上显式声明所需最小角色并在测试用例里写一道“低权限用户执行该操作必须被拒绝”的用例。这条用例不通过就不允许合入代码。5. 常见故障排查实录权限系统那些“玄学”问题5.1 权限配置了就是不生效先查缓存和生效时机权限系统最常见的故障是“我给用户配置了角色但他还是提示无权限”。操作系统、压测工具任何一个环节都可能打破预期。除了感叹一句“权限系统有玄学”之外排查思路其实有章可循。排障顺序从内到外走一遍用户是否被正确加入角色角色是否被正确分配权限用户是否同时存在于其他组或角色从而“短路”了权限中心/网关的缓存是否过期是否有规则触发了拒绝优先级高于允许多数问题都出在缓存上修改了角色权限但权限中心本地缓存还没更新或者用户会话里的角色列表还是旧的。解决办法是角色变更后主动发一个“缓存失效”事件。另一个隐蔽问题是“允许”和“拒绝”的优先级。设计规则时一定要明确拒绝优先还是允许优先。大部分安全系统应该默认拒绝优先谁能保证一个人因为身处某个组而“意外获得权限”时条件判断是或逻辑还是与逻辑就很容易出现权限范围蔓延。5.2 会话过期导致误判“未授权”前端要会区分403和401另一种常见情况是“提示无权限”但实际原因是登录态过期了。很多团队把会话过期的错误码和权限拒绝的错误码都用401返回前端拿到401后就统一提示“没有权限访问”把用户绕进了死胡同。正确的语义是401代表未认证你是谁403代表未授权虽然知道你是谁但你不能干这个。我在评审前端代码时习惯看一下对HTTP状态码的处理逻辑401应该走重新登录或者静默刷新Token403才应该提示“无权限”。这两个状态混在一起用户和技术支持都会被误导。后端同学也要注意未登录和未授权必须返回不同的状态码别偷懒都返回200再在业务体里放错误码那样对故障定位很不友好。小技巧在响应体里增加一个标准的错误码字段比如codePERMISSION_DENIED、codeTOKEN_EXPIRED前端根据错误码分支处理这样即使代理层把状态码改了排查起来也能一眼看懂。5.3 账号权限“莫名”变大多为角色继承与组嵌套问题“这个员工刚入职怎么有管理员权限”“我们只给测试开了只读权限他居然能改数据”——这类问题的根源通常不是管理员的误操作而是角色继承和组嵌套机制产生了权限叠加。很多系统的用户组支持多级嵌套用户属于A组A组属于B组B组绑定了高权限角色。表面上看你给用户配置的角色只有普通用户实际上组继承链给他带来了额外权限。如果系统又不提供“查看用户最终权限”的透视功能权限被放大后很难定位。排查这种问题时一定要给权限中心做一个“用户权限全量视图”的功能输入用户输出他通过所有路径获得的最终权限集合并标明每条权限的来源直接分配、从组继承、从角色映射。没有这个视图权限排查就是大海捞针。权限设计时还要限制组嵌套深度比如最多两层防止继承链无限延长。5.4 接口权限与前端按钮权限不一致兜底逻辑不能省很多权限问题的“最后一根稻草”是前端页面和后端接口的权限判断不一致。前端根据用户角色隐藏了某个按钮但后端对应接口没有校验权限或者前端放开了按钮后端却要求一个更高的角色。这类不一致在复杂项目中几乎必然出现因为按钮显隐逻辑是前端写死的后端接口权限是另一个模块控制的两边可能不是同一拨人维护。我的立场很明确前端按钮隐藏只是“体验优化”不是安全措施。真正的安全底线必须在后端接口上。也就是说无论前端是否显示某个按钮后端都必须独立校验该接口权限。同时接口文档里要明确定义每个接口的最小权限要求前端按这个要求做按钮显隐两边保持一致。另外要建议定期做一次“权限一致性巡检”拉取前端权限列表和后端接口权限清单做比对标出不一致项并修复。这个巡检可以做成自动化工具每周跑一次运行时间很短但价值很高。6. 从一次授权到一套体系权限治理的维护之道6.1 建立权限目录让每个接口都能找到“主人”权限治理和代码治理类似核心目标是“知道谁负责什么、如何变更、如何审计”。比较好的起点是建立一张权限目录表把系统里所有受控资源、所属模块、负责人、授权模式、最近变更记录都登记进去。这样每个接口都能找到“主人”权限申请、审批、变更都有据可查。我见过一些大型企业的做法是直接用配置中心管理权限策略权限目录跟配置中心联动修改走发布流程。这种模式在规范性上更强但流程较重适合大团队小团队用一张数据库表加一个管理后台就够关键是“有目录”和“有变更记录”。6.2 自动化审计定期扫描是权限治理的保鲜剂权限体系最大的威胁不是设计时的问题而是时间带来的腐化员工转岗、离职、项目合作结束后账号权限没有清理角色越加越细冗余膨胀特权账号长期无人review。没有定期审计权限系统会慢慢从“最小权限”变成“最大权限”。自动化扫描能做的事情很多定期枚举“超管”账号检查是否都是必要人员比对离职人员名单与有效账号找出未清理的僵尸账号扫描长期未登录但保持高权限的账号分析角色间权限重叠度是否过高。这类扫描脚本写起来不复杂关键是固化到发布流程或者定时任务里而不是想起来才做。6.3 权限回收时间窗离职、转岗与节假日权限回收是一场与遗忘的赛跑。离职员工的账号权限如果没及时回收被外部攻击者拿到就会变成一大风险。实操中我强烈建议把权限回收跟HR流程打通员工离职审批通过时系统自动发起权限回收动作目标时间不超过24小时。转岗、兼职、外包退场的权限回收同样重要。转岗员工往往拥有新旧两个岗位的权限叠加这正是越权的高发状态。我遇到过不止一次员工从运营转到市场结果还能访问旧部门的敏感报表因为没人主动回收旧角色。所以转岗流程里必须有一个“权限清理检查单”确认新角色权限的同时注销旧岗位的全部相关角色。节假日是权限治理的盲区长假前临时开放的权限假期结束没人管。建议节后第一天跑一次权限变更回滚扫描凡是“临时授权”且有效期已过的一律强制回收。6.4 个人实操体会安全评审清单里必问的五个问题这么多年下来我总结了一套权限相关的安全评审清单每次上线前都会照着过一遍。这五个问题看起来简单但每次都有团队在某个问题上翻车第一每个接口是否都有明确的授权模型没有授权逻辑的接口一律不准上线。第二数据级权限行级/字段级是否在数据访问层强制校验只依赖前端过滤的默认不通过。第三身份校验和权限校验是否解耦Token里是否保存了可信任的权限数据导致回收滞后第四临时授权是否有自动失效机制失效后的回收是否自动化第五日志是否记录了“谁在什么时间通过什么路径获得了什么权限”没有权限操作审计日志出了事连追责都追不了。这五个问题背后其实都在追问同一件事你的权限体系是“被动响应式”还是“持续治理式”。前者出问题再修后者日常就在防止问题发生。我的经验是把权限当成一次性的建设任务一定会劣化只有把它当成一座持续打理的花园定期浇水修枝才能长期保持安全与效率的平衡。如果系统还处于早期阶段哪怕权限模块做得简陋一点也不可怕只要把“目录、审批、回收、审计”这几根柱子立住了后面再引入更复杂的模型和策略都有地基。反过来哪怕权限功能再花哨缺了治理机制也撑不了多久。这就是授权与访问控制这门“老课”真正值钱的部分。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑