shiro框架的简单入门使用
1.shiro框架的简介
1.1 shiro框架是什么
shiro是apache公司的产品,是一款轻量级的java安全框架,Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架。
现在市场上使用的比较多的安全框架还有就是Spring公司的security框架,它是一款重量级的框架。shiro是一个轻量级的框架,可以快速,轻松的获取任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。它支持多种语言的应用程序,shiro支持web mvc的环境,也支持其他各种语言的程序,比如c,c#…所以shiro的使用非常灵活方便
1.2 shiro框架的核心
shiro的身份验证、授权、密码学、会话管理是其核心,是shrio的四大基石。
Authentication身份认证:对一个用户的身份进行验证,判断这个用户是否登录,是否是该系统的合法用户。
Authorization授权:即对通过认证之后的用户,对其权限进行判断,判断该用户是否有执行某一功能的权限。
Cryptography密码学:通过shiro提供的加密的算法,对数据进行加密,使数据安全同时易于使用。
Session Management会话管理:shiro提供的会话管理,不依赖与web的session,所以shiro可以在非web的环境下使用。
2.shiro框架
2.1 从shiro外部来看
Application code:就是外部应用程序
Subject:就是外部应用程序交互的用户,其实就是当前用户对象
SecurityManager:安全管理器,这个是核心对象,用来管理的所有的Subject对象,就是用来管理所有的用户的。
Realm:shiro是从 realm上获取到安全数据的,即用户,角色,权限数据,就是我们的元数据都是从realm中获取的。
2.2 从shiro内部来看
shiro的简单使用
3.1 导入shiro的依赖包
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
3.2 准备元数据,自定义一个realm类
上面是shiro中的realm的结构体系,realm是一个顶层接口,之前说过realm是获取用户,角色,权限数据的,下面有一个实现类jdbcrealm,通过这个可以从数据库中获取到用户、角色、权限这些数据。
不过我们一般都是使用自定义的realm,realm虽然是数据源,但它不仅仅是获取数据的,我们在自定义的realm类中还有认证授权验证的相关代码。
下面是自定义的realm类:我们自定义的时候不要实现realm顶层接口,因为需要复写所以抽象方法,而是通过实现AuthorizingRealm类,这样只需要覆写doGetAuthenticationInfo登录认证和doGetAuthorizationInfo授权认证的方法。
public class MyRealm extends AuthorizingRealm {
@Override
public String getName() {
return "MyRealm";
}
/**身份验证的方法
* @param authenticationToken : 参数authenticationToken对象也有两个属性:principal(对象) 和 credentials(对象)
* @return :返回AuthenticationInfo对象,该对象有两个属性:principals(集合) 和 credentials(对象)
* @throws AuthenticationException
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.通过authenticationToken获取到用户信息,如果要获取到username和password等信息就需要强转
String username = ((UsernamePasswordToken) authenticationToken).getUsername();
//拿到用户名以后就要进行身份验证了
if(username==null){
//返回一个空表示账户错误
return null;
}
//然后通过用户名拿到密码:
String pwd = getPwd(username);
//拿到用户名和密码以后就调用Simp
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, pwd, getName());
return simpleAuthenticationInfo;
}
/**
*
* @param principalCollection 参数:是一个principals集合,注意我们在身份验证方法的返回值SimpleAuthenticationInfo对象
* 中,new这个对象的第一个参数是principal对象,如果传入的是username,那么这里取出来的就是username
* 传入的是一个对象,在授权验证的参数中取出来的就是一个对象
* @return :返回一个AuthorizationInfo对象,其子类是SimpleAuthorizationInfo,这个对象有两个重要属性:getroles:获取到用户的角色
* getObjectPermissions获取到角色对应的权限
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//一个主体可以有多个principals,但只有一个Primaryprincipal,一般是用户名/密码/手机号。
//先获取到Primaryprincipal,然后上面传入的username,就可以直接强转为username
String username = (String)principalCollection.getPrimaryPrincipal();
//通过SimpleAuthorizationInfo来设置用户的角色和权限,后期这些数据是从数据库中拿到的
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//为该用户设置角色---角色使用的是set集合
Set<String> set = new HashSet<String>();
set.add("admin");
simpleAuthorizationInfo.setRoles(set);
//为这个角色赋予权限,使用的还是set集合,可以使用一个先清除一下即可
set.clear();
set.add("employee:*");
simpleAuthorizationInfo.setStringPermissions(set);
//然后将设置好的SimpleAuthorizationInfo对象返回去
return simpleAuthorizationInfo;
}
//我们还没有连接数据库,所以在这里定义一个方法,获取一个密码数据
String getPwd(String username){
//如果用户名是admin就返回123456
if("root".equals(username)){
return "123456";
}
//否则密码返回空
return null;
}
}
3.3 测试
我们自定义的realm类中的用户,角色,权限是元数据,因为没有连接数据都是假数据
@Test
public void testMyRealm()throws Exception{
//首选要准备元数据,即创建MyRealm对象
MyRealm myRealm = new MyRealm();
//然后拿到securityManager对象加载元数据
DefaultSecurityManager securityManager = new DefaultSecurityManager();
securityManager.setRealm(myRealm);
//配置上下文环境
SecurityUtils.setSecurityManager(securityManager);
//拿到当前的用户信息
Subject user = SecurityUtils.getSubject();
//判断用户是否登录
if(!user.isAuthenticated()){
//没有登录就模拟登录,使用UsernamePasswordToken对象
UsernamePasswordToken token = new UsernamePasswordToken("root","123456");
try {
user.login(token);
} catch (AuthenticationException e) {
e.printStackTrace();
System.out.println("用户名或密码错误");
}
}
//打印用户登录了没有
System.err.println("是否登录"+user.isAuthenticated());
//测试该用户是否有这个角色
System.err.println("是否有该角色"+user.hasRole("admin"));
//测试权限
System.err.println("是否有权限"+user.isPermitted("employee:index"));
//登出
user.logout();;
System.err.println("是否登录"+user.isAuthenticated());
}