Shiro权限控制《一》
shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证、用户授权。
shiro不依赖于spring,shiro不仅可以实现 web应用的权限管理,还可以实现c/s系统,分布式系统权限管理,shiro属于轻量框架,越来越多企业项目开始使用shiro。
使用shiro实现系统 的权限管理,有效提高开发效率,从而降低开发成本。
一.先上例子
1.配置pom.xml加jar包
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
2.ini配置文件
#用户信息配置 [users] admin=123,role1 #自定义配置secrityManage的相关依赖 [main] realmDemo=com.hc360.shiro.realm.RealmDemo securityManager.realms=$realmDemo #角色 [roles] role1=user:create,user:update role2=user:create,user:delete
3.自定义realms(可以不加,realms有两个方法:一个是认证:判断用户名和密码是否正确、一个是授权:从数据库里查出权限,判断是否拥有权限)
package com.hc360.shiro.realm; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; 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.authc.UnknownAccountException; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; public class RealmDemo extends AuthorizingRealm{ /** * 认证,登陆时调用 * * @author liuzunli * @date 2016-4-20 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String) token.getPrincipal(); System.out.println(username); //判断用户名是否正确 if(!"admin".equals(username)){ throw new UnknownAccountException();//或者return null; } String password = "123"; return new SimpleAuthenticationInfo(username,password,this.getName()); } /** * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用 * * @author liuzunli * @date 2016-4-20 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //认证设置的第一个参数 String username = (String) principals.getPrimaryPrincipal(); //返回的权限信息 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); //通过用户名查询用户的角色 Set<String> roleList = new HashSet<String>(); roleList.add("role1"); simpleAuthorizationInfo.setRoles(roleList); //通过用户名查询数据库、查出用户拥有的权限----- List<String> permissionList = new ArrayList<String>(); permissionList.add("user:create"); permissionList.add("user:delete"); permissionList.add("user:update"); simpleAuthorizationInfo.addStringPermissions(permissionList); return simpleAuthorizationInfo; } }
4.测试
package com.hc360.shiro; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; import org.junit.Test; /** * shiro测试 * * @author liuzunli * @date 2016-4-20 */ public class ShiroTest { /** * 登录/退出 * * @author liuzunli * @date 2016-4-20 */ @Test public void testLogin() { //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager Factory<SecurityManager> factory = new IniSecurityManagerFactory("resources\\shiro.ini"); //2、得到SecurityManager实例 并绑定给SecurityUtils SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证) Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("admin", "123"); try { //4、登录,即身份验证 subject.login(token); } catch (AuthenticationException e) { //5、身份验证失败 e.printStackTrace(); } System.out.println("是否认证通过:"+subject.isAuthenticated()); System.out.println("是否拥有角色:"+subject.hasRole("role1")); System.out.println("是否拥有权限:"+subject.isPermitted("user:create")); //6、退出 subject.logout(); System.out.println("退出后是否认证通过:"+subject.isAuthenticated()); } }
上边就是一个完整的shiro例子
二.shiro架构

subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。
securityManager:安全管理器,主体进行认证和授权都 是通过securityManager进行。
authenticator:认证器,主体进行认证最终通过authenticator进行的。
authorizer:授权器,主体进行授权最终通过authorizer进行的。
sessionManager:web应用中一般是用web容器对session进行管理,shiro也提供一套session管理的方式。
SessionDao: 通过SessionDao管理session数据,针对个性化的session数据存储需要使用sessionDao。
cache Manager:缓存管理器,主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和ehcache整合对缓存数据进行管理。
realm:域,领域,相当于数据源,通过realm存取认证、授权相关数据。
注意:在realm中存储授权和认证的逻辑。
cryptography:密码管理,提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能。
比如 md5散列算法。
三.下面再看例子
1.配置文件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"]
2.shiro流程
- 1、通过ini配置文件创建securityManager
- 2、调用subject.login方法主体提交认证,提交的token
- 3、securityManager进行认证,securityManager最终由ModularRealmAuthenticator进行认证。
- 4、ModularRealmAuthenticator调用IniRealm(给realm传入token) 去ini配置文件中查询用户信息
- 5、IniRealm根据输入的token(UsernamePasswordToken)从 shiro-first.ini查询用户信息,根据账号查询用户信息(账号和密码)
- 如果查询到用户信息,就给ModularRealmAuthenticator返回用户信息(账号和密码)
- 如果查询不到,就给ModularRealmAuthenticator返回null
- 6、ModularRealmAuthenticator接收IniRealm返回Authentication认证信息
- 如果返回的认证信息是null,ModularRealmAuthenticator抛出异常(org.apache.shiro.authc.UnknownAccountException)
- 如果返回的认证信息不是null(说明inirealm找到了用户),对IniRealm返回用户密码 (在ini文件中存在)和 token中的密码 进行对比,如果不一致抛出异常(org.apache.shiro.authc.IncorrectCredentialsException)
3.自定义realms
1.什么情况下用realms:大多数情况下都要用realms,因为大多数情况下,用户认证、用户权限等都是从数据库里取出来的,因此ini配置文件实际上大多数情况下没有,因为里边的数据都是从数据库里查出来的。
2.realms里有2个方法:doGetAuthenticationInfo:认证,一般情况下form表单提交过来的数据,然后通过这个方法连接数据库查询用户信息,判断用户名和密码是否正确。返回AuthenticationInfo对象,里边会包含用户、密码、盐等信息
doGetAuthorizationInfo:授权,认证方法返回的用户信息,然后查询数据库,把此用户的权限和角色取出来,放在放回的对象AuthorizationInfo里
4.测试
//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("resources\\shiro.ini");
//2、得到SecurityManager实例 并绑定给SecurityUtils
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("admin", "123");
try {
//4、登录,即身份验证
subject.login(token);
} catch (AuthenticationException e) {
//5、身份验证失败
e.printStackTrace();
}
System.out.println("是否认证通过:"+subject.isAuthenticated());
System.out.println("是否拥有角色:"+subject.hasRole("role1"));
System.out.println("是否拥有权限:"+subject.isPermitted("user:create"));
//6、退出
subject.logout();
System.out.println("退出后是否认证通过:"+subject.isAuthenticated());
浙公网安备 33010602011771号