首页 > 代码库 > shiro

shiro

1 权限管理

1.1 什么是权限管理

  • 基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授予的资源
  • 权限管理包括用户认证和授权,简称认证授权。对于需要访问控制的资源用户首先经过身份认证,认证通过后用户具有访问该资源的权限才可访问。

 

1.2 用户身份认证

1.2.1 概念

  • 身份认证,就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式就是系统通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确。对于采用指纹等系统,则处于指纹;对于硬件key等刷卡系统,则需要刷卡。

1.2.2 用户名密码身份认证流程

技术分享

1.2.3 关键对象

  • 上述流程图中需要理解的关键对象:

 

  • subject:主体
    • 访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体。
  • principal:身份信息
    • 是主体进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱等,一个主体可以有多个身份,但是必须有一个主身份(primary principal)。
  • credential:凭证信息
    • 只有主体自己知道的安全信息,如密码、证书等。      

 

1.3 授权

1.3.1 概念

  • 授权,即访问控制,控制谁能访问那些资源。主体进行身份认证后需要分配权限方可访问系统的资源,对于某些资源没有权限是无法访问的。

1.3.2 授权流程

技术分享

 

1.3.3 关键对象

  • 授权可以理解为who对what(which)进行how的操作。

 

  • who
    • 即主体(subject),主体在认证通过后系统进行访问控制。  
  • what(which)
    • 即资源(Resource),如系统菜单、页面、按钮、类方法、系统商店信息等。资源包括资源类型和资源实例,比如商品信息为资源类型,类型为01的商品为资源实例,编号为001的商品信息也属于资源实例。
    • 简而言之,主体必须具备资源的访问权限才可以访问该资源。  
  • how
    • 即权限/许可(permission),规定了主体对资源的操作许可,权限离开资源没有任何意义,如用户查询权限、用户添加权限、某个类方法的调用权限、编号为001用户的修改权限等,通过权限可以知道主体对那些资源有操作许可。
    • 权限可以分为粗粒度和细粒度权限,粗粒度权限是指对资源类型的权限,细粒度权限是对资源实例的权限。  

 

  • 主体、资源、权限的关系如下图

技术分享

 

 

1.3.4 分配权限

  • 用户需要分配相应的权限才可访问相应的资源。权限是对资源的操作许可。
  • 通常给用户分配资源权限需要将权限信息持久化,比如储存在关系数据库中。

 

1.3.5 权限模型

  • 针对上述的主体、资源、权限可以通过数据模型来表示。
    • 主体(账号、密码等)
    • 资源(资源名称、访问地址)
    • 权限(权限名称,资源id)
    • 角色(角色名称)
    • 主体和角色的关系(主体id、角色id)
    • 角色和权限的管理(角色id、权限id)

技术分享

 

备注】:

  • 为什么权限和资源是多对一的关系?

 

  • 答:在系统中系统是固定的,比如我们写的方法、系统中的按钮、菜单等等,那么,想想对于一个菜单来说,如果我们给系统管理员角色分配全部权限,那么是不是系统管理员可以访问一切资源。而如果我们给人力资源总监角色只分配几个权限,那么是不是人力资源总监也可能可以访问这个菜单。所以综上所述,权限和资源是多对一的关系。

 

  • 但是在通常企业开发中将资源和权限合并为一张权限表
      • 权限(权限名称,资源id)
      • 资源(资源名称,访问URL)
    • 合并为:
      • 权限(权限名称、资源名称、资源访问地址)    

技术分享

 

备注】:上图被称为权限管理的通用模型,不过企业在开发的时候会根据系统自身的特点进行修改。

 

1.3.6 权限控制

  • 用户拥有了权限即可操作权限范围内的资源,系统不知道主体是否具有访问权限所以需要对用户的访问进行口控制。

1.3.6.1 基于角色的访问控制

  • RBAC(Role Based Access Control)基于角色的访问控制,是以角色为中心进行访问控制,比如:主体的角色为总经理可以查询企业运营报表,查询员工工资信息等,访问控制流程如下:

技术分享

  • 上图中的逻辑代码如下
if(主体.hasRole("总经理角色")){
    查询工资  
}
  • 这种方式是有缺点:以角色进行访问控制粒度较粗,如上图所示,如果查询工资所需要的角色变化为总经理和部门经理,此时就需要修改逻辑判断为“判断用户的角色是否为总经理角色或部门经理角色”,系统扩展性较差。
  • 修改代码如下:
if(主体.hasRole("总经理角色") || 主体.hasRole("部门经理角色")){
    查询工资  
}

 

1.3.6.2 基于资源的访问控制

  • RBAC(Resource Based Access Control)基于资源的访问控制,比如主体必须具有查询工资权限才可以查询员工工资信息等。
  • 实现的逻辑代码如下:
if(主体.hasPermission("查询工资权限")){
  查询工资  
}
  • 优点:系统设计时定义好查询工资的权限标识,即使查询工资所需要的角色变化为总经理和部门经理也只需要将“查询工资权限”添加到“部门经理角色”的权限列表中,判断逻辑不用修改,系统可扩展性强。

 

2 权限管理解决方案

2.1 粗粒度和细粒度

2.1.1 什么是粗粒度和细粒度?

  • 对资源类型的管理称为粗粒度权限管理,即只控制到菜单、按钮、方法,粗粒度的例子比如:用户具有用户管理的权限,具有导出订单明细的权限。
  • 对资源实例的控制称为细粒度权限管理,即只控制到数据级别的权限。比如:用户只允许修改本部门的员工信息,用户只允许导出自己创建的订单明细。

2.1.2 如何实现粗粒度和细粒度?

  • 如何实现粗粒度权限管理?
    • 粗粒度权限管理比较容易将权限管理的代码抽取出来在系统架构级别统一处理。比如:通过SpringMVC的拦截器。
  • 如何实现细粒度权限管理?
    • 对细粒度权限管理在数据级别是没有共性可言的,针对细粒度权限管理就是企业业务逻辑的一部分,如果在也完成处理相对比较简单,如果将细粒度权限管理统一在系统架构级别去抽取,比较困难,即使抽取的功能也存在扩展性不强。
    • 建立细粒度权限管理在业务层去控制。
    • 比如:部门经理只查询本部门的员工信息,在service层接口提供一个部门id的参数,在Controller层中根据用户的信息得到该用户属于哪个部门,调用Service时将部门id传入Service层,实现该用户只查询本部门员工信息。    

 

shiro