Shiro权限框架 概述
Shiro 可以帮助我们完成:认证(登录)、授权(访问控制)、密码加密、会话管理、与 Web 集成、缓存等
Shiro 主要组件:
Subject
:主体可以是当前的操作用户、程序等,在程序任意位置可使用:Subject subject = SecurityUtils.getSubject() 获取到 Subject 主体对象
SecurityManager
:它是 Shiro 功能实现的核心,负责与其他组件(认证器,授权器,缓存控制器等)进行交互,实现 Subject 委托的各种功能,类似于springmvc中的 DispatcherServlet 前端控制器,负责进行分发调度
Realms
:可以把 Realm 看成 DataSource,即安全数据源。执行认证(登录)和授权(访问权限)时,Shiro 会从应用配置的 Realm 中查找相关的比对数据, 以确认用户是否合法,操作是否合理。
Authenticator(认证器)
:用于认证,返回boolean类型
Authorizer(授权器)
:用户访问控制授权
SessionManager
:支持会话管理
CacheManager
:用于缓存认证授权信息等
Cryptography(加密组件)
:用于加密解密的工具包
Shiro 认证
基于 ini 的认证:
创建一些对象组装好,调用login方法,在登录的时候SecurityUtils委托给SecurityManager对象处理,SecurityManager对象又找Authenticator(认证器),认证器又从Realm对象中查找相关的比对数据,这是底层自动帮我们完成的
- 创建**
Security Manager
**: Security Manager(安全管理器)来提供安全服务的,所以用shiro的时候需要创建该对象- 主体**
Subject
提交请求给Security Manager
**- **
Security Manager
调用Authenticator
**组件做认证- **
Authenticator
通过Realm
**来从数据源中获取认证数据
-
添加依赖
org.apache.shiro shiro-core 1.5.2
-
编写shiro-authc.ini配置文件
用户的身份、凭据
[users]
hkj=123
yoona=456 -
使用 Shiro 相关的 API 完成身份认证
@Test public void testAuthenticator(){ //构建环境,向SecurityManager管理器中组装对象 DefaultSecurityManager securityManager = new DefaultSecurityManager(); //需指定Realm对象,并配置给安全管理器,加载shiro.ini配置,得到配置中的用户信息 IniRealm realm = new IniRealm("classpath:shiro-authc.ini"); securityManager.setRealm(realm); SecurityUtils.setSecurityManager(securityManager); //获取Subject对象进行认证操作 Subject subject = SecurityUtils.getSubject(); //创建令牌(存储了账号和密码) UsernamePasswordToken token = new UsernamePasswordToken("hkj","123"); subject.login(token); System.out.println("认证的结果:" + subject.isAuthenticated()); }
基于自定义 Realm 的认证
-
创建自定义Realm对象继承AuthorizingRealm(拥有缓存,认证,授权功能)
public class UserRealm extends AuthorizingRealm { //提供认证数据的 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //token封装了用户或程序传过来的用户名和密码 //String userName = (String) token.getPrincipal(); UsernamePasswordToken t = (UsernamePasswordToken)token; String username = t.getUsername(); //通过用户名去数据库查询用户信息(模拟) User user = DataMapper.getUserByName(username); if(user == null){ return null; } //在返回的user对象中封装了密码,可以让Shiro底层自行帮我们比对密码 //参数一:查询出来的user对象(类似往session中存入的对象) 参数二:封装的密码(数据库中的密码) 参数三:指定realm的名字 return new SimpleAuthenticationInfo(user,user.getPassword(),this.getName()); } //提供授权数据的 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } }
-
使用 Shiro 相关的 API 完成身份认证
@Test public void testUserRealm(){ //构建环境,向SecurityManager管理器中组装对象 DefaultSecurityManager securityManager = new DefaultSecurityManager(); //需指定Realm对象,并配置给安全管理器 UserRealm realm = new UserRealm(); securityManager.setRealm(realm); SecurityUtils.setSecurityManager(securityManager); //获取Subject对象进行认证操作 Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("hkj","123"); subject.login(token); System.out.println("认证的结果:" + subject.isAuthenticated()); subject.logout(); System.out.println("认证的结果:" + subject.isAuthenticated()); }
Web环境Shiro认证
Shiro 授权
基于 ini 的授权:
创建一些对象组装好,调用login方法,在登录的时候SecurityUtils委托给SecurityManager对象处理,SecurityManager对象又找Authorizer(授权器),授权器又从Realm对象中查找相关的比对数据,目前我们所需要的就是将用户拥有的角色和权限告知 Shiro
- 创建**
Security Manager
**- 主体**
subject
**授权- 主体授权是交给**
Security Manager
**授权- Security Manager调用授权器**
Authorizer
**授权- 通过**
Realm
在数据库或者缓存中来获取授权的数据(角色数据和权限数据**)
-
添加依赖
org.apache.shiro shiro-core 1.5.2
-
编写shiro-authc.ini配置文件
#用户的身份、凭据、角色
[users]
hkj=123,hr,seller
yoona=456,seller#角色与权限信息
[roles]
hr=user:list,user:delete
seller=customer:list,customer:save -
使用 Shiro 相关的 API 完成身份授权
@Test public void testAuthor(){ //构建环境,向SecurityManager管理器中组装对象 DefaultSecurityManager securityManager = new DefaultSecurityManager(); //需指定Realm对象,并配置给安全管理器 IniRealm realm = new IniRealm("classpath:shiro-author.ini"); securityManager.setRealm(realm); SecurityUtils.setSecurityManager(securityManager); //获取Subject对象进行认证操作 Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("yoona","456"); subject.login(token); // 判断用户是否有某个角色 System.out.println("是否有 hr 角色?" + subject.hasRole("hr")); System.out.println("是否有 seller 角色?"+ subject.hasRole("seller")); // 是否同时拥有多个角色 System.out.println("是否同时拥有hr和seller?" + subject.hasAllRoles(Arrays.