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>
maven依赖
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
ini配置文件
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;
}
}
realms
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"]
ini配置文件解释
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认证信息
- org.apache.shiro.authc.UnknownAccountException)
- 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());