概述

在大多数系统中,都或多或少需要认证授权模型/系统的支持。

认证/授权是什么?最简单的,我们的系统要求用户必须在“登录”之后才允许进行一些操作。“登录”的过程就是认证;而区别与未登录状态,只允许登录用户进行一些操作,这就是授权。认证与授权相互独立,有协同配合,共同支撑起系统对安全的基本要求。

认证与授权

认证的目的在于认出用户。日常生活中,我们通过视觉、声音等因素认出一个人。但是就网络应用而言,应用最多只能够认识到发起请求的浏览器、手机APP、物联网设备等用户代理(User Agent),也无法直接地将用户与用户代理进行绑定。因此,向应用证明操作这些用户代理的实体就成了至关重要的步骤。你需要通过密码、手机验证码、人脸识别或其它形式凭证来完成“登录”操作,即认证。

当然了,我们也认识到,不是所有的操作都需要一个这般复制“登录”流程的,即使这些操作逻辑上也需要认出背后的用户是谁。这部分所使用到的技术就是“会话管理”了。在一定的有效期范围内,用户无需重复证明自己的身份,而用户-应用间保持最基本的信任。当然,一般来说,修改密码等危险操作还是需要再次进行认证。

总而言之,无论是“登录”认证抑或是“会话”认证,其目的都是为了认出用户。

完成认证之后,就要启用授权了。授权负责的是控制用户能干什么。管理员和普通员工所能进行的操作肯定是有所差别的。借助于前置认证提供用户身份信息,授权将对用户的操作进行决断。

访问控制(权限控制)

授权旨在界定用户能够进行哪些操作,而访问控制正是进行授权界定的措施、手段。该如何实施访问控制呢?看人下菜是最简单、最容易被接受的方式——为每个用户独立地分配权限。但是,就Web应用而言,如此行事的代价将是及其巨大的。动辄几十万、上百万…的用户量,又如何维护得起这般细致的控制呢。而且,每个用户独立设置权限,同时也意味着每个权限需要直接对接百十万的用户。

撇开可行性,访问控制做的就是这种活计——控制主体(用户)对客体(系统、API等)的操作。

主要的访问控制技术分为三类:自主访问控制、强制访问控制、基于角色的访问控制

自主访问控制(Discretionary Access Control,DAC)

  • 每个客体都独立维护一张访问控制表(Access Control List, ACL)
  • 每个客体都有一个所有者
  • 所有者可以将其负责的客体访问权限分配给其它用户
  • 每次主体对客体的访问都面向ACL做确认后执行
  • 强依赖于所有者对安全要求的认知

强制访问控制(Mandatory Access Control, MAC)

  • 预置相应的密级,例如绝密级、机密级和普通级。密级有强弱关系
  • 每个主体/客体都分配一个密级
  • 每次主体对客体的操作,判定主体密级 >= 客体密级即允许访问

基于角色的访问控制(Role-Based Access Control, RBAC)

  • 角色作为一系列有较强相关性权限的持有者
  • 用户通过被分配一系列角色,从而间接地拥有权限集

一般来说,DAC、MAC都不太适合于Web应用的访问控制。因此,后续的讨论都将基于RBAC进行。

控制粒度

如何定义一个客体,就涉及到控制粒度了。就Web应用而言,比较粗略的有数据粒度、方法粒度、URL粒度、系统粒度等等。任意粒度,都可以作为访问控制的组成部分,作为授权的一部分。但是,粒度的控制也会导致一些相当致命的问题。

越权问题就是一种粒度控制下的问题。

纵向访问控制

顾名思义,纵向访问控制所控制的权限拥有一定的优先级概念,例如管理员操作与普通用户操作。特别适合于使用强制访问控制的解决方案,使用RBAC也并不困难,基本上只要定义两类角色也能解决。业内对于这类问题的解决方案相当成熟,需要的只是根据不同的业务场景进行适配。

横向访问控制

对于横向访问控制,问题就不再那么的简单。在方法粒度下的RBAC模型,很容易就会导致A用户事实上访问了B用户数据的问题发生,也就是横向越权。而想要实现数据粒度的通用模型,却又不可避免地将对业务代码进行侵入。

控制粒度的取舍,就很大程度上取决于Web应用的实际需求。

小结

认证、授权的基本目的在于满足对安全的基本要求,其涉及的知识相当广泛。本篇的目的,仅仅在于阐释认证、授权两个术语的基本定义,并对访问控制技术做概要式的介绍。

  __                    __                  
 / _| __ _ _ __   __ _ / _| ___ _ __   __ _ 
| |_ / _` | '_ \ / _` | |_ / _ \ '_ \ / _` |
|  _| (_| | | | | (_| |  _|  __/ | | | (_| |
|_|  \__,_|_| |_|\__, |_|  \___|_| |_|\__, |
                 |___/                |___/