SpringBoot整合Shiro学习(上)
SpringBoot整合Shiro(上)
基于【编程不良人】2020最新版Shiro教程,整合SpringBoot项目实战教程
哔哩哔哩链接:https://www.bilibili.com/video/BV1uz4y197Zm?p=1
一、权限的管理
1.1 什么是权限管理
基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。
权限管理包括用户身份认证和授权两部分,简称认证授权。对于需要访问控制的资源用户首先经过身份认证,认证通过后用户具有该资源的访问权限方可访问。
1.2 什么是身份认证
身份认证,就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确。对于采用指纹等系统,则出示指纹;对于硬件Key等刷卡系统,则需要刷卡。
1.3 什么是授权
授权,即访问控制,控制谁能访问哪些资源。主体进行身份认证后需要分配权限方可访问系统的资源,对于某些资源没有权限是无法访问的
二、什么是shiro
Apache Shiro™ is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications.
Shiro 是一个功能强大且易于使用的Java安全框架,它执行身份验证、授权、加密和会话管理。使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序—从最小的移动应用程序到最大的web和企业应用程序。
Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能
,组成了一个通用的安全认证框架。
三、shiro的核心架构
3.1 Subject
Subject即主体,外部应用与subject进行交互,subject记录了当前操作用户,将用户的概念理解为当前操作的主体,可能是一个通过浏览器请求的用户,也可能是一个运行的程序。
Subject在shiro中是一个接口,接口中定义了很多认证授相关的方法,外部程序通过subject进行认证授,而subject是通过SecurityManager安全管理器进行认证授权
3.2 SecurityManager
SecurityManager即安全管理器,对全部的subject进行安全管理,它是shiro的核心,负责对所有的subject进行安全管理。通过SecurityManager可以完成subject的认证、授权等,实质上SecurityManager是通过Authenticator进行认证,通过Authorizer进行授权,通过SessionManager进行会话管理等。
SecurityManager是一个接口,继承了Authenticator, Authorizer, SessionManager这三个接口。
3.3 Authenticator
Authenticator即认证器,对用户身份进行认证,Authenticator是一个接口,shiro提供ModularRealmAuthenticator实现类,通过ModularRealmAuthenticator基本上可以满足大多数需求,也可以自定义认证器。
3.4 Authorizer
Authorizer即授权器,用户通过认证器认证通过,在访问功能时需要通过授权器判断用户是否有此功能的操作权限。
3.5 Realm
Realm即领域,相当于datasource数据源,securityManager进行安全认证需要通过Realm获取用户权限数据,比如:如果用户身份数据在数据库那么realm就需要从数据库获取用户身份信息。
注意:不要把realm理解成只是从数据源取数据,在realm中还有认证授权校验的相关的代码。
3.6 SessionManager
sessionManager即会话管理,shiro框架定义了一套会话管理,它不依赖web容器的session,所以shiro可以使用在非web应用上,也可以将分布式应用的会话集中在一点管理,此特性可使它实现单点登录。
3.7 SessionDAO
SessionDAO即会话dao,是对session会话操作的一套接口,比如要将session存储到数据库,可以通过jdbc将会话存储到数据库。
3.8 CacheManager
CacheManager即缓存管理,将用户权限数据存储在缓存,这样可以提高性能。
3.9 Cryptography
Cryptography即密码管理,shiro提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能。
四、shiro中的认证
4.1 认证
身份认证,就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确。
4.2 shiro中认证的关键对象
Subject:主体
访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体;Principal:身份信息
是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)。credential:凭证信息
是只有主体自己知道的安全信息,如密码、证书等。
4.3 认证流程
4.4 认证的开发
1. 创建springboot项目并引入shiro依赖
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.5.3</version>
</dependency>
2. 引入shiro配置文件
配置文件:名称随意,以 .ini
结尾,放在 resources
目录下,我们此处创建一个shiro.ini
文件
注意:在实际的项目开发中并不会使用这种方式,这种方法可以用来初学时练手
[users]
表示我们的所有用户,以键=值的方式存放用户名密码,我们的shiro.ini
文件内容如下:
[users]
zhangsan=123456
lisi=456789
3.开发认证代码
我们在项目的的test
目录下编写代码测试,测试发现认证通过,因为我们的的用户名和密码与shiro.ini
中的对应。
测试代码如下:
package com.example.demo;import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class DemoApplicationTests {/* ini方式认证测试 */@Testvoid contextLoads() {// 1.创建安全管理器对象,所有认证和授权都在安全管理器对象中进行,DefaultSecurityManager实现了SecurityManager接口DefaultSecurityManager securityManager = new DefaultSecurityManager();// 2.给安全管理器设置realm(securityManager进行安全认证需要通过Realm获取用户权限数据)securityManager.setRealm(new IniRealm("classpath:shiro.ini"));// 3.SecurityUtils:全局的安全工具类,我们需要借助它完成认证、退出等操作,// 给全局安全工具类设置安全管理器SecurityUtils.setSecurityManager(securityManager);// 4.关键对象subject主体// 拿到当前登录的主体对象Subject subject = SecurityUtils.getSubject();// 5.创建令牌,用户名密码的令牌,此处我们假设要登录的用户名为 zhangsan ,密码为 123UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");try {System.out.println("认证状态" + subject.isAuthenticated());// 未认证状态,fasle//用户认证subject.login(token);System.out.println("认证状态" + subject.isAuthenticated()); //是否认证成功} catch (UnknownAccountException e) {e.printStackTrace();System.out.println("认证失败,用户名不存在");} catch (IncorrectCredentialsException e) {e.printStackTrace();System.out.println("认证失败,密码错误");}}
}
如果认证不通过,会报异常,以下是shiro认证常见的异常类型
:
4.shiro认证常见的异常类型
UnknownAccountException(用户名异常)
IncorrectCredentialsException(密码错误异常)
DisabledAccountException(帐号被禁用)
LockedAccountException(帐号被锁定)
ExcessiveAttemptsException(登录失败次数过多)
ExpiredCredentialsException(凭证过期)等
4.5 自定义Realm
通过分析shiro源码可知,shiro的认证:
1.最终执行用户名比较是在SimpleAccountRealm类
的 doGetAuthenticationInfo
方法中完成用户名校验
2.最终密码校验是在 AuthenticatingRealm
类 的assertCredentialsMatch
方法 中(密码的校验由shiro自动完成)
自定义Realm的作用:放弃使用.ini文件,使用数据库查询用户数据
上面我们的测试使用的是Shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm。
1.shiro提供的Realm
2.根据认证源码发现认证使用的是SimpleAccountRealm
总结shiro的认证与授权:
认证 : AuthenticatingRealm 类中的 doGetAuthenticationInfo中
授权 :AuthorizingRealm 类中的 doGetAuthorizationInfo中
弄懂认证和授权要重写的方法后,我们自定义一个realm,继承 AuthorizingRealm ,并重写本类AuthorizingRealm
的doGetAuthorizationInfo
方法(授权)和父类AuthenticatingRealm
的doGetAuthenticationInfo
方法(认证),
重写方法,我们此处先书写认证的代码,认证需要我们返回一个AuthenticationInfo对象
,我们可以使用SimpleAuthenticationInfo
或者SimpleAccount
,一般我们使用SimpleAuthenticationInfo
,
认证代码如下(授权我们在后面进行学习):
package com.example.demo.shiro.realm;import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;public class CustomerRealm extends AuthorizingRealm {/* 授权 */@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {return null;}/* 认证 */@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {// authenticationToken.getPrincipal() 即用户名,我们可以强转类型为string// 在token中获取 用户名String principal = (String) authenticationToken.getPrincipal();System.out.println(principal);// 实际开发中应当 根据身份信息使用jdbc mybatis查询相关数据库,在这里只做简单的演示// 假设username,password是从数据库获得的信息String username="zhangsan";String password="123";if(username.equals(principal)){// 参数1:返回数据库中正确的用户名// 参数2:返回数据库中正确密码// 参数3:提供当前realm的名字,realm的名字都是程序运行时底层生成的 我们直接调用父类中的this.getName(); 即可SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal,password,this.getName());return simpleAuthenticationInfo;}return null;}
}
之后我们在项目test目录下新建一个测试方法,测试发现输出了我们的用户名和登录成功,
具体测试代码如下:
/* 自定义realm认证测试 */@Testvoid contextLoads1() {// 1.创建安全管理对象 securityManagerDefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();// 2.给安全管理器设置realm(设置为自定义realm获取认证数据)defaultSecurityManager.setRealm(new CustomerRealm());// IniRealm realm = new IniRealm("classpath:shiro.ini");// 3.给安装工具类中设置默认安全管理器SecurityUtils.setSecurityManager(defaultSecurityManager);// 4.获取主体对象subjectSubject subject = SecurityUtils.getSubject();// 5.创建token令牌,这里假设用户输入的用户名为zhangsan,密码为123UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");try {subject.login(token);// 用户登录System.out.println("登录成功~~");} catch (UnknownAccountException e) {e.printStackTrace();System.out.println("用户名错误!!");} catch (IncorrectCredentialsException e) {e.printStackTrace();System.out.println("密码错误!!!");}}
扩展:查看某个类的继承关系
我们在ideal中 输入代码 Realm ,再按快捷键crtl+h
可查看Realm的继承关系
或者右键它,点击 show Diagram
,可以查看类图
ps:如果右键没有Diagrams,可能是因为你未安装对应的插件,在ideal的插件里搜索UML
和jBoss jBPM
依次进行安装,之后重启ideal即可。
在弹出的界面右键,即可查看对象的关系
4.6 使用MD5加密算法
MD5算法
作用:一般用来加密或者签名
特点:MD5算法不可逆,如何内容相同无论执行多少次md5生成结果始终是一致
网络上提供的MD5在线解密一般是用穷举的方法
生成结果:始终是一个16进制32位长度字符串
MD5的基本使用:
shiro集成了md5的加密算法,我们先来了解md5的基本使用,我们继续在项目的test包下新建测试方法进行测试,
测试代码如下:
/* 密码md5加密处理 */@Testvoid contextLoads2() {// 使用md5Md5Hash md5Hash = new Md5Hash("123");System.out.println(md5Hash.toHex());// 使用MD5 + salt处理,默认salt是加在123的前面的,即对 X0*7ps123 进行加密Md5Hash md5Hash1 = new Md5Hash("123", "X0*7ps");System.out.println(md5Hash1.toHex());// 使用md5 + salt + hash散列(参数代表要散列多少次,一般是 1024或2048),散列的次数越多越安全Md5Hash md5Hash2 = new Md5Hash("123", "X0*7ps", 1024);System.out.println(md5Hash2.toHex());}
之后我们想要对我们的密码进行加密处理,在前面源码的分析中我们知道shiro中密码的比较是在 AuthenticatingRealm
类下的assertCredentialsMatch
方法中进行比较,且默认是equal
比较(shiro的默认密码比较器是SimpleCredentialsMacher
,而我们点进去SimpleCredentialsMacher
源码发现这个密码比较器默认就是equal比较)
由此我们知道 getCredentialsMatcher
用于获取密码比较器,那么我们可以知道它肯定有setCredentialsMatcher
方法用于设置密码比较器,
我们右键 CredentialsMatcher
点击 Show Diagram
查看它的继承关系
结果如下,发现它有三个实现方法,因为我们想要对密码进行md5的加密方法,所以我们选择HashedCredentialsMatcher
的密码比较器
之后我们需要更改默认的密码比较器,我们需要更改代码,注意,shiro的md5加密有三种方法,一是单独使用md5进行加密的方式
,二是使用md5+salt加密的方式
,三是使用md5+salt+hash加密的方式
,接下来我们逐一介绍。
单独使用md5加密的方式
我们需要更改自定义CustomerRealm.java的认证方法,将密码改为进行md5加密后的密码
之后新增测试方法进行测试,测试方法指定使用的密码比较器和加密方式(注意,HashedCredentialsMatcher
这个密码比较器里面有很多种加密方式,md5加密
只是其中的一种,所以我们需要指定使用的加密算法为md5),测试发现登录成功,
测试代码如下:
/* 自定义realm认证测试-加密方式为md5或md5+salt */@Testvoid contextLoads3() {// 1.创建安全管理器DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();// 2.注入realmCustomerRealm realm = new CustomerRealm();// 3.设置realm使用hash凭证匹配器HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();// 声明:使用的算法credentialsMatcher.setHashAlgorithmName("md5");realm.setCredentialsMatcher(credentialsMatcher);defaultSecurityManager.setRealm(realm);// 4.将安全管理器注入安全工具SecurityUtils.setSecurityManager(defaultSecurityManager);// 5.通过安全工具类获取subjectSubject subject = SecurityUtils.getSubject();// 6.认证UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");try {subject.login(token);System.out.println("登录成功");} catch (UnknownAccountException e) {e.printStackTrace();System.out.println("用户名错误");} catch (IncorrectCredentialsException e) {e.printStackTrace();System.out.println("密码错误");}}
使用md5+salt加密的方式
我们也需要修改CustomerRealm.java的认证方法,将密码改为进行md5+slat
加密后的密码,同时通过ByteSource.Util.bytes(随机盐)
的方式将随机盐告诉shiro,ByteSource这个接口是shiro源码中的,用于将盐告诉shiro,具体代码如下:
/* 认证 */@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {// authenticationToken.getPrincipal() 即用户名,我们可以强转类型为string// 在token中获取 用户名String principal = (String) authenticationToken.getPrincipal();System.out.println(principal);// 实际开发中应当 根据身份信息使用jdbc mybatis查询相关数据库,在这里只做简单的演示// 假设username,password是从数据库获得的信息String username="zhangsan";String password="8a83592a02263bfe6752b2b5b03a4799";if(username.equals(principal)){// 参数1:返回数据库中正确的用户名// 参数2:返回数据库中正确密码// 参数3:通过ByteSource.Util.bytes(随机盐)的方式将随机盐告诉shiro// 参数4:提供当前realm的名字,realm的名字都是程序运行时底层生成的 我们直接调用父类中的this.getName(); 即可SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal,password, ByteSource.Util.bytes("X0*7ps"),this.getName());return simpleAuthenticationInfo;}return null;}
我们继续回到test目录下进行测试,我们的测试方法和md5加密的测试方法是一样的,不用更改代码,运行测试发现登录成功
使用md5+salt+hash加密的方式
我们也需要修改CustomerRealm的认证方法,将密码改为进行md5+slat+散列
加密后的密码,同时通过ByteSource.Util.bytes(随机盐)的方式将随机盐告诉shiro,
我们继续回到test目录下进行测试,新增测试方法,运行测试发现登录成功
- 注意,此处需要将散列的次数告诉shiro,因为如果不将散列的次数告诉shiro,那么它
默认只会进行散列一次
,即我们上面介绍的md5+salt加密就是散列一次
测试代码如下:
/* 自定义realm认证测试-加密方式为md5+salt+散列次数 */@Testvoid contextLoads5() {// 1.创建安全管理器DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();// 2.注入realmCustomerRealm realm = new CustomerRealm();// 3.设置realm使用hash凭证匹配器HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();// 声明:使用的算法credentialsMatcher.setHashAlgorithmName("md5");// 声明:散列次数credentialsMatcher.setHashIterations(1024);realm.setCredentialsMatcher(credentialsMatcher);defaultSecurityManager.setRealm(realm);// 4.将安全管理器注入安全工具SecurityUtils.setSecurityManager(defaultSecurityManager);// 5.通过安全工具类获取subjectSubject subject = SecurityUtils.getSubject();// 6.认证UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");try {subject.login(token);System.out.println("登录成功");} catch (UnknownAccountException e) {e.printStackTrace();System.out.println("用户名错误");} catch (IncorrectCredentialsException e) {e.printStackTrace();System.out.println("密码错误");}}
五、shiro中的授权
5.1 授权
授权,即访问控制,控制谁能访问哪些资源。主体进行身份认证后需要分配权限方可访问系统的资源,对于某些资源没有权限是无法访问的。
5.2 关键对象
授权可简单理解为who对what(which)进行How操作:
Who,即主体(Subject),主体需要访问系统中的资源。
What,即资源(Resource),如系统菜单、页面、按钮、类方法、系统商品信息等。资源包括资源类型和资源实例,比如商品信息为资源类型,类型为t01的商品为资源实例,编号为001的商品信息也属于资源实例。
How,权限/许可(Permission),规定了主体对资源的操作许可,权限离开资源没有意义,如用户查询权限、用户添加权限、某个类方法的调用权限、编号为001用户的修改权限等,通过权限可知主体对哪些资源都有哪些操作许可。
5.3 授权流程
5.4 授权方式
基于角色的访问控制
RBAC基于角色的访问控制(Role-Based Access Control)是以角色为中心进行访问控制
if(subject.hasRole("admin")){//操作什么资源 }
基于资源的访问控制
RBAC基于资源的访问控制(Resource-Based Access Control)是以资源为中心进行访问控制
if(subject.isPermission("user:update:01")){ //资源实例//对资源01用户具有修改的权限 } if(subject.isPermission("user:update:*")){ //资源类型//对 所有的资源 用户具有更新的权限 }
5.5 权限字符串
权限字符串的规则是:资源标识符:操作:资源实例标识符,意思是对哪个资源的哪个实例具有什么操作,“:”是资源/操作/实例的分割符,权限字符串也可以使用*通配符。
例子:
- 用户创建权限:
user:create
,或user:create:*
- 用户修改实例001的权限:
user:update:001
- 用户实例001的所有权限:
user:*:001
5.6 shiro中授权编程实现方式
编程式
Subject subject = SecurityUtils.getSubject(); if(subject.hasRole(“admin”)) {//有权限 } else {//无权限 }
注解式
@RequiresRoles("admin") public void hello() {//有权限 }
标签式
JSP/GSP 标签:在JSP/GSP 页面通过相应的标签完成: <shiro:hasRole name="admin"><!— 有权限—> </shiro:hasRole> 注意: Thymeleaf 中使用shiro需要额外集成!
5.7 开发授权
我们在CustomerRealm中书写授权的代码,具体代码如下:
package com.example.demo.shiro.realm;import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;public class CustomerRealm extends AuthorizingRealm {/* 授权 */@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {// 一个主体可以有多个身份,但只能有一个主身份// 拿到主身份信息,即用户名String primaryPrincipal = (String)principalCollection.getPrimaryPrincipal();System.out.println("身份信息: "+primaryPrincipal); //用户名// 根据身份信息 用户名 获取当前用户的角色信息,以及权限信息SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();// 假设 admin,user 是从数据库查到的 角色信息simpleAuthorizationInfo.addRole("admin");simpleAuthorizationInfo.addRole("user");// 假设 ... 是从数据库查到的 权限信息赋值给权限对象simpleAuthorizationInfo.addStringPermission("user:*:01");// 第三个参数为*则可以省略simpleAuthorizationInfo.addStringPermission("prodect:*");return simpleAuthorizationInfo;}/* 认证 */@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {// authenticationToken.getPrincipal() 即用户名,我们可以强转类型为string// 在token中获取 用户名String principal = (String) authenticationToken.getPrincipal();System.out.println(principal);// 实际开发中应当 根据身份信息使用jdbc mybatis查询相关数据库,在这里只做简单的演示// 假设username,password是从数据库获得的信息String username="zhangsan";String password="e4f9bf3e0c58f045e62c23c533fcf633";if(username.equals(principal)){// 参数1:返回数据库中正确的用户名// 参数2:返回数据库中正确密码// 参数3:通过ByteSource.Util.bytes(随机盐)的方式将随机盐告诉shiro// 参数4:提供当前realm的名字,realm的名字都是程序运行时底层生成的 我们直接调用父类中的this.getName(); 即可SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal,password, ByteSource.Util.bytes("X0*7ps"),this.getName());return simpleAuthenticationInfo;}return null;}
}
我们继续回到test目录下进行测试,新增测试方法,测试代码如下:
/* 自定义realm认证测试-加密方式为md5+salt+散列次数,授权测试 */@Testvoid contextLoads6() {//1.创建安全管理器DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();//2.注入realmCustomerRealm realm = new CustomerRealm();//3.设置realm使用hash凭证匹配器HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();//声明:使用的算法credentialsMatcher.setHashAlgorithmName("md5");//声明:散列次数credentialsMatcher.setHashIterations(1024);realm.setCredentialsMatcher(credentialsMatcher);defaultSecurityManager.setRealm(realm);//4.将安全管理器注入安全工具SecurityUtils.setSecurityManager(defaultSecurityManager);//5.通过安全工具类获取subjectSubject subject = SecurityUtils.getSubject();//6.认证UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");try {subject.login(token);System.out.println("登录成功");} catch (UnknownAccountException e) {e.printStackTrace();System.out.println("用户名错误");} catch (IncorrectCredentialsException e) {e.printStackTrace();System.out.println("密码错误");}// 授权if (subject.isAuthenticated()) {// 基于角色权限控制System.out.println(subject.hasRole("admin"));// 基于多角色的权限控制,hasAllRoles需要的是一个集合对象,我们可以通过Arrays.asList("admin", "user")将其转换为集合// hasAllRoles表示同时需要有这些角色,注意:每次判断都会调用一次授权方法,如下面两个角色的判断就调用两次授权方法(doGetAuthorizationInfo)System.out.println(subject.hasAllRoles(Arrays.asList("admin", "user")));System.out.println(subject.hasAllRoles(Arrays.asList("admin", "manager")));// 是否具有其中一个角色boolean[] booleans = subject.hasRoles(Arrays.asList("admin", "user", "manager"));for (boolean aBoolean : booleans) {System.out.println(aBoolean);}System.out.println("====这是一个分隔符====");// 基于权限字符串的访问控制 资源标识符:操作:资源类型// 用户具有的权限 *:*:* 表示所有权限,即超级管理员// user:*:01 表示对user的01资源具有任意的操作权限 prodect:* 表示对product的任意资源具有任意的操作权限System.out.println("权限:" + subject.isPermitted("user:update:01"));System.out.println("权限:" + subject.isPermitted("prodect:update:02"));// 分别具有哪些权限boolean[] permitted = subject.isPermitted("user:*:01", "user:update:02");for (boolean b : permitted) {System.out.println(b);}//同时具有哪些权限,要都有才返回trueboolean permittedAll = subject.isPermittedAll("prodect:*:01", "prodect:update:03");System.out.println(permittedAll);}}
测试结果如下:
源码获取
至此,我们的SpringBoot整合Shiro(上)
就讲解完成了。中篇我们将进行Shiro与Jsp页面整合
的讲解。源码和数据库文件可以通过关注我的微信公众号 我爱学习呀嘻嘻
,回复关键字shiro集成
进行获取哦。
SpringBoot整合Shiro学习(中):Shiro与Jsp页面整合
SpringBoot整合Shiro学习(下):Shiro与Thymeleaf整合
SpringBoot整合Shiro学习(上)相关推荐
- SpringBoot整合Shiro搭建登录注册认证授权权限项目模板
主要内容: 1 SpringBoot整合Shiro安全框架; 2 Shiro主要学习内容总结;(执行流程.主要对象接口.注意事项等) 3 Redis实现对权限信息缓存; ! 温馨提示: 想要快速搭Sh ...
- SpringBoot整合Shiro实现权限管理与登陆注册
前言 Shiro解决了什么问题? 互联网无非就是一些用户C想要使用一些服务S的资源去完成某件事,S的资源不能说给谁用就给谁用,因此产生了权限的概念,即C必须有权限才能操作S的资源.S如何确定C就是C呢 ...
- 降龙十八掌之 springboot整合shiro(含MD5加密)
java学习爱好者 2019-05-27 16:21:00 开发环境: 1.mysql - 5.7.21 2.navicat(mysql客户端管理工具) 3.idea 2017 4.jdk9 5.to ...
- springboot整合shiro使用shiro-spring-boot-web-starter
此文章仅仅说明在springboot整合shiro时的一些坑,并不是教程 增加依赖 <!-- 集成shiro依赖 --> <dependency><groupId> ...
- springboot整合shiro和session的详细过程和自定义登录拦截器
文章目录 1.shiro依赖 2.shiro配置 shiro过滤器配置: 关联自定义的其他管理器 自定义会话工厂: 3.登陆时记录用户信息 4.shiro一些工具类的学习 5.自定义登录拦截器 shi ...
- SpringBoot整合Shiro实现登录认证和授权CHCache
文章目录 一. springboot实现普通登录 1 添加依赖 2 编写配置文件 3 新建实体类和mapper 4 编写业务层代码 5 编写控制器 6 编写启动类 7 编写登录页面和主页面 二. sp ...
- 补习系列(6)- springboot 整合 shiro 一指禅
欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...
- SpringBoot整合Shiro实现权限控制,验证码
本文介绍 SpringBoot 整合 shiro,相对于 Spring Security 而言,shiro 更加简单,没有那么复杂. 目前我的需求是一个博客系统,有用户和管理员两种角色.一个用户可能有 ...
- SpringBoot 整合Shiro 一指禅
目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...
最新文章
- python将照片转文字_Python将图片转化成文字
- 偶然的一次渗透从弱口令->docker逃逸
- locate: database too small: /var/db/locate.databas
- mysql操作手册我_MySQL使用指南一
- 编写Maven插件的提示
- 李洋疯狂C语言之求素数的方法
- matlab磁铁模拟,用matlab-模拟环形磁铁的磁场分布
- mysql group by_MySQL优化GROUP BY方案
- 利用深度学习从大脑活动合成语言,应对人类语音挑战
- 禾川plc编程软件_HCP Works下载 HCP Works(禾川PLC编程软件) v2.26.01.92012 官方安装版 下载-脚本之家...
- 了不起的 Deno:带你极速获取各大平台今日热榜
- 入门OJ 1256【排队】
- linux测试wifi信噪比,无线网络中信噪比(SNR)计算
- 编程中的数学——编程遇见数学,让数学更有趣!
- 【presto】presto 查询hive分桶表问题
- linux 繁体中文转为简体,linux - 安装OpenCC(简体繁体转换)
- 信号灯管理服务器CPU型号,正文-新华三集团-H3C
- 关于阅读英语文献的一些整理方法
- 如何成为一名合格的LINUX系统管理员
- 中小水库中的水情遥测系统如何实现远程监控和自动报警?
热门文章
- 手持云台 1.前期准备
- Java基础eclipse版(二)——JDK、Eclipse的下载与安装
- 全景感知、智能融合|视图计算平台全新发布
- H5 LayaAir实现复制微信号到剪切板功能
- C# Dictionary多线程安全访问问题
- 【2】C++语法与数据结构之MFC_CList学生管理系统_链表内排序_函数指针
- html5视频制作,iH5最专业的H5制作工具
- 拨号ECS和拨号VPS的区别
- 英特尔奔腾芯片漏洞_什么是奔腾(英特尔)?
- 新南威语言班C加,【干货来了】新南威尔士大学UEEC语言班 你了解多少?