Shiro

  • 学习目标

    1. 基于url权限管理和shiro基础

    2. shiro与企业web项目整合开发的方法

  • 权限管理

    1. 用户认证

    2. 用户授权

  • shiro基础

    1. shiro架构

    2. shiro进行用户认证的方法

    3. shiro进行用户授权的方法

什么是权限管理

只要有用户参与的系统,一般都需要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源

分为用户认证和授权两部分

用户认证

概念

用户去访问系统,系统要验证用户身份的合法性,最常用的用户身份验证的方法:

  1. 用户名密码

  2. 指纹打卡机

  3. 基于证书的验证方法…

系统验证用户身份合法,用户方可访问系统的资源

关键对象

  • subject:主体 理解为用户,可能是程序,都要去访问系统的资源,系统需要对subject进行身份认证

  • principal:身份信息,通常是唯一的,一个主体还有多个身份信息,但是都有一个主身份信息(primary principal)

  • credential:凭证信息,可以是密码,证书,指纹

总体:主体在进行身份认证时需要提供身份信息和凭证信息

用户授权

概念

简单理解为访问控制,在用户认证通过后,系统对用户访问资源进行控制,用户具有资源的访问权限方可访问

关键对象

  • 授权的过程理解为:who对what(which)进行how操作

  • who:主体即subject,subject在认证通过后系统进行访问控制

  • what(which):资源(Resource),subject必须具备资源的访问权限方可访问该资源。资源比如:系统用户列表页面、商品修改菜单、商品id为001的商品信息

    • 资源分为资源类型和资源实例

    • 系统的用户信息就是资源类型,相当于java类

    • 系统中id为001的用户就是资源实例相当于new的java对象

  • how:权限/许可(permission),针对资源的权限或许可,subject具有permission,如何访问/操作需要定义permission,比如:用户添加、用户修改、商品删除

分配权限

用户需要分配相应的权限才可访问相应的资源。权限是对于资源的操作许可

通常给用户分配资源权限需要将权限信息持久化,比如存储在关系数据库中

权限控制(授权核心)

基于角色的访问控制(RBAC-Role based access control)
比如:
系统角色包括:部门经理,总经理(角色针对用户来划分)

系统代码中实现:

1
2
3
4
//如果该user是部门经理则可以访问if中的代码
if(user.hasRole('部门经理')){
//代码
}

问题:
角色针对人划分的,人作为用户在系统中属于活动内容,如果该角色可以访问的资源出现变更,需要修改你的代码了,比如:需求变更为部门经理和总经理都可以查看用户报表,代码改为
1
2
3
if(user.hasRole('部门经理')|| user.hasRole('总经理')){
//代码
}

基于角色的访问控制是不利于系统维护的(可拓展性不强)

基于资源的访问控制(RBAC-Resource based access control)
资源在系统中是不变的,比如资源有:类中的方法,页面中的按钮

对资源的访问需要具有permission权限,代码可以写为:

1
2
3
if(user.hasPermission('用户报表查看')){
//代码
}

这种方式可以解决用户角色变更不用修改权限控制的代码

如果需要变更权限只需要在分配权限模块去操作,给部门经理或总经理增或删除权限

所以建议使用基于资源的访问控制

权限管理解决方案

什么是粗粒度和细粒度权限

  • 粗粒度:对资源类型的权限管理

    • 资源类型:菜单,url链接,用户添加页面,用户信息,类方法,页面中按钮

    • 比如:超级管理员可以访问用户添加页面,用户信息等全部页面;部门管理员可以访问用户信息页面

  • 细粒度:对资源实例的权限管理,数据级别的权限管理

    • 资源实例:就是资源类型的具体化,比如:用户id为001的修改连接,1110班的用户信息,行政部的员工

    • 部门经理只可以访问本部门的员工信息,用户只可以看到自己的菜单,大区经理只可以查看本辖区的销售订单

如何实现

粗粒度

比较容易将权限管理的代码抽取出来在系统架构级别统一处理

比如:通过springmvc的拦截器实现授权

细粒度

在数据级别没有共性可言,针对细粒度权限管理就是业务逻辑的一部分,如果在业务层去处理相对比较简单,如果将细粒度权限管理统一在系统架构级别去抽取,比较困难,即使抽取的功能可能也存在扩展性不强

建议细粒度权限管理在业务层去控制

比如:部门经理只查询本部门员工信息,在service接口提供一个部门id的参数,controller中根据当前用户的信息得到该用户属于哪个部门,调用service将部门id传入service,实现该用户只查询本部门的员工