shiro框架

权限管理*

    为什么需要权限管理
1、安全性:误操作、人为破坏、数据泄露等,比如对数据库的操作,普通的开发人员对数据的操作只有查询等操作,而DBA可以对数据库进行最高权限的操作。
2、数据隔离:不同权限能看到及操作不同的数据,比如对应部门的领导只能看到该部门下的员工数据。
3、明确职责:运营和客服等不同角色,Leader和dev等不同级别。比如去哪网等这些网上商城,客服可以看到所有的订单信息,而运营只能看到他们负责的那些商户的信息。客服可以看到客户购买商品后的反馈情况,运营能看到店铺的交易额等数据而客服就看不到

权限管理核心
1、用户-权限:用户绑定权限,使用在人员少,功能固定或者特别简单的系统,mysql使用的就是这种权限。
2、RBAC(Role-Based Access Control):用户-角色-权限,基于角色的权限访问控制,适用于所有的场景。user、role和permission是多对多的关系,一个用户可以有多个角色,一个角色可以有多个用户,可以很方便灵活的切换用户的角色和权限。而且可以衍生出组的概念,这个组下的所有用户都拥有相同的角色,比如经理组,该组下的成员都拥有相同的角色。可以直接对该组进行授权

shiro框架_第1张图片

1.3、理想的权限管理
1、能实现角色级权限:基于RBAC模型实现
2、实现功能级、数据级权限:该用户是否有权限去使用某功能或者对某数据有什么操作方式
3、提供可视页面:提供页面可以操作用户、角色、权限,可以对其进行修改等操作,方便我们对系统进行维护
1.4、相关操作界面
1、权限管理界面:权限模块的概念,支持对权限的增删改查
2、角色管理界面:对角色的增删改查
3、用户管理界面:用户的增删改查,希望对group概念的实现,将用户放到部门里,对部门进行增删改查
4、角色和权限关系维护界面:每个角色已经配置的权限
5、用户和角色关系维护界面:每个角色已经包含的用户等可以在页面上进行修改
这些页面最好使用树形结构展开显示

目前主流的权限管理框架有SparingSecurity和Apache的Shiro
1.5.1、SpringSecurity
Spring Security是一个灵活和强大的身份验证和访问控制框架,以确保基于Spring的Java Web应用程序的安全。它是一个轻量级的安全框架,它确保基于Spring的应用程序提供身份验证和授权支持。它与Spring MVC有很好地集成,并配备了流行的安全算法实现捆绑在一起。安全主要包括两个操作“认证”与“验证”(有时候也会叫做权限控制)。“认证”是为用户建立一个其声明的角色的过程,这个角色可以一个用户、一个设备或者一个系统。“验证”指的是一个用户在你的应用中能够执行某个操作。在到达授权判断之前,角色已经在身份认证过程中建立了
1.5.1.1、SpringSecurity核心组件
Web/Http 安全:这是最复杂的部分。通过建立 filter 和相关的 service bean 来实现框架的认证机制。当访问受保护的 URL 时会将用户引入登录界面或者是错误提示界面。
业务对象或者方法的安全:控制方法访问权限的。
AuthenticationManager:处理来自于框架其他部分的认证请求。
AccessDecisionManager:为 Web 或方法的安全提供访问决策。会注册一个默认的,但是我们也可以通过普通 bean 注册的方式使用自定义的 AccessDecisionManager。
AuthenticationProvider:AuthenticationManager 是通过它来认证用户的。
UserDetailsService:跟 AuthenticationProvider 关系密切,用来获取用户信息的

1.5.2、Apache Shiro
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序
1.5.2.1、Shiro核心组件
subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。
securityManager:安全管理器,主体进行认证和授权都是通过securityManager进行,是shiro的心脏。
realm:域,领域,相当于数据源,通俗意义的DAO层,通过realm存取认证、授权相关数据

1.5.3、两者比较
Shiro比Spring更容易使用,实现和最重要的理解
Spring Security却有更好的社区支持
Apache Shiro在Spring Security处理密码学方面有一个额外的模块
SpringSecurity 对spring 结合较好,如果项目用springmvc ,使用起来很方便。但是如果项目中没有用spring,那就不要考虑它了。
Shiro 功能强大、且简单、灵活。是Apache 下的项目比较可靠,且不跟任何的框架或者容器绑定,可以独立运行。
总的来说Shiro就可以满足我们的需求了。
1.6、系统安全性解决方案
Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,这个主体可以是用户、设备也可以是其他系统。也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。

二、Shiro

2.1、概述
Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在 JavaSE 环境,也可以用在 JavaEE 环境。Shiro 可以帮助我们完成:认证、授权、加密、会话管理、与 Web 集成、缓存等。这不就是我们想要的嘛,而且 Shiro 的 API 也是非常简单;其基本功能点如下图所示
shiro框架_第2张图片
Authentication:身份认证 / 登录,验证用户是不是拥有相应的身份;
Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE 环境的,也可以是 Web 环境的;
Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
Web Support:Web 支持,可以非常容易的集成到 Web 环境;
Caching:缓存,比如用户登录后,其用户信息、拥有的角色 / 权限不必每次去查,这样可以提高效率;
Concurrency:shiro 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
Testing:提供测试支持;
Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

记住一点,Shiro 不会去维护用户、维护权限;这些需要我们自己去设计 / 提供;然后通过相应的接口注入给 Shiro 即可

2.2、Shiro的优势

从 2003 年至今,框架选择方面的情况已经改变了不少,但今天仍有令人信服的理由让你选择 Shiro。其实理由相当多,Apache Shiro:

1、易于使用 - 易用性是这个项目的最终目标。应用安全有可能会非常让人糊涂,令人沮丧,并被认为是“必要之恶”【译注:比喻应用安全方面的编程】。若是能让它简化到新手都能很快上手,那它将不再是一种痛苦了。

2、广泛性 - 没有其他安全框架可以达到 Apache Shiro 宣称的广度,它可以为你的安全需求提供“一站式”服务。

3、灵活性 - Apache Shiro 可以工作在任何应用环境中。虽然它工作在 Web、EJB 和 IoC 环境中,但它并不依赖这些环境。Shiro 既不强加任何规范,也无需过多依赖。

4、Web 能力 - Apache Shiro 对 Web 应用的支持很神奇,允许你基于应用 URL 和 Web 协议(如 REST)创建灵活的安全策略,同时还提供了一套控制页面输出的 JSP 标签库。

5、可插拔 - Shiro 干净的 API 和设计模式使它可以方便地与许多的其他框架和应用进行集成。你将看到 Shiro 可以与诸如 Spring、Grails、Wicket、Tapestry、Mule、Apache Camel、Vaadin 这类第三方框架无缝集成。

6、支持 - Apache Shiro 是 Apache 软件基金会成员,这是一个公认为了社区利益最大化而行动的组织。项目开发和用户组都有随时愿意提供帮助的友善成员。

2.3、外部看Shiro
Shiro的核心概念有三个:Subject,SecurityManager 和 Realms
shiro框架_第3张图片
2.3.1、Subject
主体,代表了当前 “用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是 Subject,如网络爬虫,机器人等;即一个抽象概念;所有 Subject 都绑定到 SecurityManager,与 Subject 的所有交互都会委托给 SecurityManager;可以把 Subject 认为是一个门面;SecurityManager 才是实际的执行者;

在考虑应用安全时,你最常问的问题可能是“当前用户是谁?”或“当前用户允许做 X 吗?”

当我们写代码或设计用户界面时,问自己这些问题很平常:应用通常都是基于用户构建的,

并且你希望功能描述(和安全)是基于每个用户的。所以,对于我们而言,考虑应用安全的最自然方式就是基于当前用户。

Shiro 的 API 用它的 Subject 概念从根本上体现了这种思考方式。

在应用程序中,我们可以在任何地方获取当前操作的用户主体:

import org.apache.shiro.subject.Subject;
import org.apache.shiro.SecurityUtils;
...
Subject currentUser = SecurityUtils.getSubject();

获得Subject 后,通过这个对象,我们可以对其进行绝大多数安全操作:登录、登出、访问会话、执行授权检查等。
Shiro 的api非常直观,它反映了开发者以“每个用户” 思考安全控制的自然趋势
2.3.2、SecurityManager
安全管理器;即所有与安全有关的操作都会与 SecurityManager 交互;且它管理着所有 Subject;可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互,如果学习过 SpringMVC,你可以把它看成 DispatcherServlet 前端控制器。

SecurityManager 是 Shiro 框架的核心,充当“保护伞”,引用了多个内部嵌套安全组件,它们形成了对象图。

但是,一旦 SecurityManager 及其内部对象图配置好,它就会退居幕后,应用开发人员几乎把他们的所有时间都花在 Subject API 调用上

一个应用只需要一个 SecurityManager,是一个单例对象。它的缺省实现是POJO,Shiro 里的其他组件也是一样。因此,可以用POJO兼容的任何配置机制进行配置:普通的Java代码、Spring xml、YAML、和 ini 文件等。基本上,能够实例化类和调用JavaBean兼容方法的任何配置形式都可以。
比如ini文件进行配置:

[main]
\#提供了对根对象securityManager及其依赖的配置
securityManager=org.apache.shiro.mgt.DefaultSecurityManager
…………
securityManager.realms=$jdbcRealm
[users]
\#提供了对用户/密码及其角色的配置,用户名=密码,角色1,角色2
username=password,role1,role2
[roles]
\#提供了角色及权限之间关系的配置,角色=权限1,权限2
role1=permission1,permission2
[urls]
\#用于web,提供了对web url拦截相关的配置,url=拦截器[参数],拦截器
/index.html = anon
/admin/** = authc, roles[admin], perms["permission1"]

然后,我们在Java代码中,可以轻而易举的获得 SecurityManager对象了

//1. 装入 INI 配置 
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
 
//2. 创建 SecurityManager 
SecurityManager securityManager = factory.getInstance();
 
//3. 使其可访问 
SecurityUtils.setSecurityManager(securityManager);

2.3.3、Realm
域,Shiro 从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。
也就是说对于我们而言,最简单的一个 Shiro 应用:
应用代码通过 Subject 来进行认证和授权,而 Subject 又委托给 SecurityManager;
我们需要给 Shiro 的 SecurityManager 注入 Realm,从而让 SecurityManager 能得到合法的用户及其权限进行判断。
从以上也可以看出,Shiro 不提供维护用户 / 权限,而是通过 Realm 让开发人员自己注入。

2.4、内部看Shiro

shiro的架构图如下所示:
shiro框架_第4张图片
Subject:主体,可以看到主体可以是任何可以与应用交互的 “用户”;
SecurityManager:相当于 SpringMVC 中的 DispatcherServlet 或者 Struts2 中的 FilterDispatcher;是 Shiro 的心脏;所有具体的交互都通过 SecurityManager 进行控制;它管理着所有 Subject、且负责进行认证和授权、及会话、缓存的管理。
Authenticator:认证器,负责主体认证的,这是一个扩展点,如果用户觉得 Shiro 默认的不好,可以自定义实现;其需要认证策略(Authentication Strategy),即什么情况下算用户认证通过了;
Authrizer:授权器,或者访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能;
Realm:可以有 1 个或多个 Realm,可以认为是安全实体数据源,即用于获取安全实体的;可以是 JDBC 实现,也可以是 LDAP 实现,或者内存实现等等;由用户提供;注意:Shiro 不知道你的用户 / 权限存储在哪及以何种格式存储;所以我们一般在应用中都需要实现自己的 Realm;
SessionManager:如果写过 Servlet 就应该知道 Session 的概念,Session 呢需要有人去管理它的生命周期,这个组件就是 SessionManager;而 Shiro 并不仅仅可以用在 Web 环境,也可以用在如普通的 JavaSE 环境、EJB 等环境;所有呢,Shiro 就抽象了一个自己的 Session 来管理主体与应用之间交互的数据;这样的话,比如我们在 Web 环境用,刚开始是一台 Web 服务器;接着又上了台 EJB 服务器;这时想把两台服务器的会话数据放到一个地方,这个时候就可以实现自己的分布式会话(如把数据放到 Memcached 服务器);
SessionDAO:DAO 大家都用过,数据访问对象,用于会话的 CRUD,比如我们想把 Session 保存到数据库,那么可以实现自己的 SessionDAO,通过如 JDBC 写到数据库;比如想把 Session 放到 Memcached 中,可以实现自己的 Memcached SessionDAO;另外 SessionDAO 中可以使用 Cache 进行缓存,以提高性能;
CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存的;因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能
Cryptography:密码模块,Shiro 提高了一些常见的加密组件用于如密码加密 / 解密的

三、Shiro认证用户

3.1、概述
身份验证,即在应用中谁能证明他就是他本人。一般提供如他们的身份 ID 一些标识信息来表明他就是他本人,如提供身份证,用户名 / 密码来证明。在web应用中一般就是登录功能。

在 shiro 中,用户需要提供 principals (身份)和 credentials(证明)给 shiro,从而应用能验证用户身份:
principals:身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。一个主体可以有多个 principals,但只有一个 Primary principals,一般是用户名 / 密码 / 手机号。

credentials:证明 / 凭证,即只有主体知道的安全值,如密码 / 数字证书等。最常见的 principals 和 credentials 组合就是用户名 / 密码了。接下来先进行一个基本的身份认证。

另外两个相关的概念是之前提到的 Subject 及 Realm,分别是主体及验证主体的数据源

3.2、环境准备

<dependencies>
    <!--单元测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.9</version>
    </dependency>
    <!--Apache推出的日志接口-->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.1.3</version>
    </dependency>
    <!--shiro核心包-->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.2.2</version>
    </dependency>
</dependencies>

maven项目搭建

[users]
zhangsan=123456
lisi=12345

身份数据
这里使用一个ini文件存储用户数据,通过[users]指定两个主体,zhangsan和lisi

@Test
public void test1(){
    //获取SecurityManager工厂,加载ini文件
    Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
    SecurityManager manager = factory.getInstance();
    //获取securityManager对象并绑定给SecurityUtils对象
    SecurityUtils.setSecurityManager(manager);
    //当前用户的主体
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123456");
    //登陆
    try{
        subject.login(token);
    }catch (UnknownAccountException e){
        System.out.println("当前用户不存在");
    }catch (IncorrectCredentialsException e){
        System.out.println("密码错误");
    }
    System.out.println(subject.isAuthenticated());
    subject.logout();
}

测试

3.3.3、说明
首先通过 new IniSecurityManagerFactory 并指定一个 ini 配置文件来创建一个 SecurityManager 工厂;
接着获取 SecurityManager 并绑定到 SecurityUtils,这是一个全局设置,设置一次即可;
通过 SecurityUtils 得到 Subject,其会自动绑定到当前线程;如果在 web 环境在请求结束时需要解除绑定;然后获取身份验证的 Token,如用户名 / 密码;
调用 subject.login 方法进行登录,其会自动委托给 SecurityManager.login 方法进行登录;
如果身份验证失败请捕获 AuthenticationException 或其子类,常见的如: DisabledAccountException(禁用的帐号)、LockedAccountException(锁定的帐号)、UnknownAccountException(错误的帐号)、ExcessiveAttemptsException(登录失败次数过多)、IncorrectCredentialsException (错误的凭证)、ExpiredCredentialsException(过期的凭证)等,具体请查看其继承关系;对于页面的错误消息展示,最好使用如 “用户名 / 密码错误” 而不是 “用户名错误”/“密码错误”,防止一些恶意用户非法扫描帐号库;
最后可以调用 subject.logout 退出,其会自动委托给 SecurityManager.logout 方法退出

3.3.4、代码身份验证流程
收集用户身份 / 凭证,即如用户名 / 密码;
调用 Subject.login 进行登录,如果失败将得到相应的 AuthenticationException 异常,根据异常提示用户错误信息;否则登录成功;
最后调用 Subject.logout 进行退出操作。
如上测试的几个问题:
用户名 / 密码硬编码在 ini 配置文件,以后需要改成如数据库存储,且密码需要加密存储;
用户身份 Token 可能不仅仅是用户名 / 密码,也可能还有其他的,如登录时允许用户名 / 邮箱 / 手机号同时登录。
3.3.5、身份认证流程
shiro框架_第5张图片
首先调用 Subject.login(token) 进行登录,其会自动委托给 Security Manager,调用之前必须通过 SecurityUtils.setSecurityManager() 设置;
SecurityManager 负责真正的身份验证逻辑;它会委托给 Authenticator 进行身份验证;
Authenticator 才是真正的身份验证者,Shiro API 中核心的身份认证入口点,此处可以自定义插入自己的实现;
Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证,默认 ModularRealmAuthenticator 会调用 AuthenticationStrategy 进行多 Realm 身份验证;
Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息,如果没有返回 / 抛出异常表示身份验证失败了。此处可以配置多个 Realm,将按照相应的顺序及策略进行访问。

3.4、Relam
3.4.1、概述
Realm:域,Shiro 从Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。如我们之前的 ini 配置方式将使用 org.apache.shiro.realm.text.IniRealm
3.4.2、自定义Realm

package com.stt.test2;

import org.apache.shiro.authc.*;
import org.apache.shiro.realm.Realm;

/**
 * ClassName: MyRealm
 * Description:
 * date: 2019/12/28 0028 下午 15:15
 *
 * @author stt
 * @since JDK 1.8
 */
public class MyRealm implements Realm {
    //返回唯一的名字
    public String getName() {
        return this.getClass().getName();
    }
    //判断是否支持此Token
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;
    }

    //验证逻辑
    public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal();//获取用户名
        String pass = new String((char[])token.getCredentials());//获取密码
        //判断
        if(!"张三".equals(username)){
            throw new UnknownAccountException("用户名错误");
        }
        if(!"123456".equals(pass)){
            throw new IncorrectCredentialsException("密码错误");//密码错误
        }
        //认证成功返回一个AuthenticationInfo对象
        return new SimpleAuthenticationInfo(username, pass, this.getName());
    }
}

3.4.3、shiro.ini文件
单Realm配置

myRealm= com.stt.test2.MyRealm
securityManager.realms=$myRealm

通过 $name 来引入之前的 realm 定义
多Realm配置

\#声明一个realm
myRealm1=com.stt.test2.MyRealm1
myRealm2=com.stt.test2.MyRealm2
\#指定securityManager的realms实现
securityManager.realms=$myRealm1,$myRealm2

securityManager 会按照 realms 指定的顺序进行身份认证。此处我们使用显示指定顺序的方式指定了 Realm 的顺序,如果删除 “securityManager.realms= m y R e a l m 1 , myRealm1, myRealm1,myRealm2”,那么securityManager 会按照 realm 声明的顺序进行使用(即无需设置 realms 属性,其会自动发现),当我们显示指定 realm 后,其他没有指定 realm 将被忽略,如 “securityManager.realms=$myRealm1”,那么 myRealm2 不会被自动设置进去。

Shiro提供的Realm
shiro框架_第6张图片
以后一般继承 AuthorizingRealm(授权)即可;其继承了 AuthenticatingRealm(即身份验证),而且也间接继承了 CachingRealm(带有缓存实现)。其中主要默认实现如下:
org.apache.shiro.realm.text.IniRealm:[users] 部分指定用户名 / 密码及其角色;[roles] 部分指定角色即权限信息;
org.apache.shiro.realm.text.PropertiesRealm: user.username=password,role1,role2 指定用户名 / 密码及其角色;role.role1=permission1,permission2 指定角色及权限信息;
org.apache.shiro.realm.jdbc.JdbcRealm:通过 sql 查询相应的信息,如 “select password from users where username = ?” 获取用户密码,“select password, password_salt from users where username = ?” 获取用户密码及盐;“select role_name from user_roles where username = ?” 获取用户角色;“select permission from roles_permissions where role_name = ?” 获取角色对应的权限信息;也可以调用相应的 api 进行自定义 sql;

四、授权
4.1、概述
授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作等)。在授权中需了解的几个关键对象:主体(Subject)、资源(Resource)、权限(Permission)、角色(Role)
4.2、主体
主体,即访问应用的用户,在 Shiro 中使用 Subject 代表该用户。用户只有授权后才允许访问相应的资源。
4.3、资源
在应用中用户可以访问的任何东西,比如访问页面、查看/编辑某些数据、访问某个业务方法、打印文本等等都是资源。用户只要授权后才能访问
4.4、权限
安全策略中的原子授权单位,通过权限我们可以表示在应用中用户有没有操作某个资源的权力。即权限表示在应用中用户能不能访问某个资源,如: 访问用户列表页面
查看/新增/修改/删除用户数据(即很多时候都是 CRUD(增查改删)式权限控制)打印文档等等。。。
如上可以看出,权限代表了用户有没有操作某个资源的权利,即反映在某个资源上的操作允不允许,不反映谁去执行这个操作。所以后续还需要把权限赋予给用户,即定义哪个用户允许在某个资源上做什么操作(权限),Shiro 不会去做这件事情,而是由实现人员提供。
Shiro 支持粗粒度权限和细粒度权限 https://blog.csdn.net/q540494685/article/details/81328168
4.5、角色
角色代表了操作集合,可以理解为权限的集合,一般情况下我们会赋予用户角色而不是权限,即这样用户可以拥有一组权限,赋予权限时比较方便。典型的如:项目经理、技术总监、CTO、开发工程师等都是角色,不同的角色拥有一组不同的权限
4.6、隐式角色
即直接通过角色来验证用户有没有操作权限,如在应用中 CTO、技术总监、开发工程师可以使用打印机,假设某天不允许开发工程师使用打印机,此时需要从应用中删除相应代码;再如在应用中 CTO、技术总监可以查看用户、查看权限;突然有一天不允许技术总监查看用户、查看权限了,需要在相关代码中把技术总监角色从判断逻辑中删除掉;即粒度是以角色为单位进行访问控制的,粒度较粗;如果进行修改可能造成多处代码修改。
4.7、显示角色
在程序中通过权限控制谁能访问某个资源,角色聚合一组权限集合;这样假设哪个角色不能访问某个资源,只需要从角色代表的权限集合中移除即可;无须修改多处代码;即粒度是以资源/实例为单位的;粒度较细。即RBAC模型。
4.8、授权方式
4.8.1、编程式:使用if else授权
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {
//有权限
} else {
//无权限
}
4.8.2、注解式:通过在执行的 Java 方法上放置相应的注解完成
@RequiresRoles(“admin”)
public void hello() {
//有权限
}
没有权限将抛出相应的异常
4.8.3、JSP/GSP标签


4.9、授权
4.9.1、基于角色访问控制(隐式角色)

你可能感兴趣的:(java基础之家)