基于角色的访问控制,英文是 Role-Based Access Control,简称 RBAC。它通过建立用户与角色的对应关系,使得每个用户可以拥有多个角色,每个角色可以拥有多个权限。基于角色的访问控制会定义多个不同的角色,不同角色实际上就是一个权限的集合。基于角色的访问控制中,不同角色之间具有高低之分,高权限角色可以访问低权限角色的资源,但是低权限角色往往不能访问高权限角色的资源。举个例子,一个教育性质的作业系统中存在老师角色与学生角色,老师角色与学生角色都具有查看作业的权限,但是学生角色不具有审批作业的权限,只有老师角色才具有审批作业的权限,如果学生角色可以进行这个操作,那么可能存在越权访问。同时,基于角色的访问控制遵守最小特权,应该授予所需要的完成其任务的最小角色,这样可以防止用户干坏事。

RBAC 是一种“用户-角色-权限”的授权模型,主要分为 RBAC0 基本模型、RBAC1 角色的分层模型、RBAC2 约束模型、RBAC3 统一模型。其中,RBAC0 是 RBAC 的核心,包括用户、角色、权限和会话。RBAC1 基于 RBAC0 进行扩展,是 RBAC 的角色分层模型,引入角色继承概念。RBAC2 基于 RBAC0 进行扩展,引入互斥角色的限制,互斥角色是指各自权限互相制约的两个角色,此外,还约束一个用户拥有的角色是有限的,一个角色拥有的权限是有限的,以及想要获取较高权限,首先需要拥有一个低级权限。RBAC3 基于 RBAC0 的基础上,将 RBAC1 和 RBAC2 进行整合,因此 RBAC3 是一种既有角色分层又有约束的一种模型。

本文主要基于 RBAC0 基本模型进行介绍“用户-角色-权限”的授权模型。基于角色的访问控制通过建立用户与角色的对应关系,使得每个用户可以拥有多个角色,每个角色可以拥有多个权限。

其中,权限限制了用户所能进行的相关操作。举个例子,一个教育性质的作业系统中存在老师角色与学生角色,学生角色具有查看作业与写作业的权限,老师角色具有查看作业与审批作业的权限,因此具有学生角色的用户是不能进行审批作业的操作。权限可以作用于菜单、API 接口、文件等资源。 在用户量大的情况下,可以对用户进行分组。此时,用户组拥有一个角色,那么用户组内的所有用户都将拥有这个角色。换句话说,引入用户组的概念后,可以建立用户组与角色的对应关系,那么用户组内的所有用户都会间接地与角色发生关系。

在实际业务开发过程,Java 语言中的 Spring Security 与 Apache Shiro 都可以建立基于角色的访问控制。这里,演示了 Spring Security 的权限拦截配置,其中设置不同角色对 URL 地址的访问权限。

@EnableWebMvcSecurity

public class ApiSecurityConfig {

    @Override

    protected void onConfigure(HttpSecurity http) throws Exception {

        http.authorizeRequests()

            // 匹配"/students/**"的所有 GET 操作,无需要任何身份认证

            .antMatchers(HttpMethod.GET, "/students/**").permitAll()

            // 匹配"/students/**"的所有 POST 操作,需要用户拥有 teacher 角色

            .antMatchers(HttpMethod.POST, "/students/**").hasAuthority("teacher")

            // 匹配"/students/**"的所有(其他)操作,需要用户拥有 admin 角色

            .antMatchers("/students/**").hasAnyAuthority("admin");

            // 其他的 URL 地址均需要加身份认证

            .antMatchers("/**").anonymous().anyRequest().authenticated();

    }

    @Override

    public void configure(WebSecurity web) throws Exception {

    }

}

总结下,基于角色的访问控制,通过建立用户与角色的对应关系,使得每个用户可以拥有多个角色,每个角色可以拥有多个权限。用户根据拥有的角色进行操作与资源访问。