shiro
shiro是一个基于java的开源的安全管理框架,可以完成认证,授权,会话管理,加密,缓存功能。
为什么学习shiro
在java的世界中,安全管理框架有spring security和shiro。spring security主要依赖于spring,并且比较复杂,学习曲线较高。shiro比较简单,而且其比较独立,既可以javaSE中使用,也可以在javaEE中使用,并且在分布式集群的环境下也可以使用。
shiro的结构体系
- Authentication认证:验证用户是否合法。==>就是验证登录;
- Authorization授权:授予谁具有访问某些资源的权限;
- SessionManagement:会话管理,用户登录后的用户信息通过SessionManagent进行管理,不管是在什么应用中
- Cryphography:提供了一些常见的加密算法,使得在应用中可以很方便的实现数据安全。
- WebSupport:提供web应用程序支持
- Caching缓存:提供了对缓存的支持,支持多种缓存架构:如ehcache,还支持缓存数据库-redis
- Concurrency:支持多线程并发访问
- Testing:测试
- Run As:支持一个用户在允许的前提下使用另一个身份进行登录;
- RememberMe:记住我
Subject=身份+凭证====>用户名和密码【用户获取主体的信息,Principals,Credentials】
Subject:
当前与软件进行交互的实体(用户,第三方服务,corn job等)的安全特定“视图”;
SecurityManager:
SecurityManager是shiro架构的心脏。它基本上是一个保护伞对象,协调其管理的组件以确保他们能够一起进行顺利的工作。他还管理每个应用程序用户的shiro的视图。因此他知道如何执行每个用户的安全操作。
Realms:
Realms担当shiro和你的应用程序的安全数据之间的桥梁或连接器。它实际上与安全相关的数据如用来执行身份验证登录及授权访问控制的用户账户交互时,shiro从一个或多个应用程序配置的Realm中寻找多个这样的东西;
realms域:用户通过shiro来完成相关的安全工作,shiro是不会去维护数据信息的。在shiro的工作过程中,数据的查询和获取工作是通过Realm从不同的数据源获取的。Realm可以获取数据库信息,文本信息等。在shiro中可以有一个realms也可以有多个。
用户认证
Authentication:用户认证,验证用户是否合法
需要提交身份和凭证给shiro。
principals:用户的的身份信息,是Subject的标识属性。能够唯一标识Subject。
Credentials:凭证:密码。是只被subjcet知道的秘密值。可以是密码,可以是数字证书等。
Principals和Credentials最常见的组合:用户名/密码。在shiro中通常使用UsernamePaswordToken来指定身份和凭证信息。
在shiro中用户认证的流程
1、新建java项目
导入
commons-beanutils-1.9.2.jar
commons-logging-1.2.jar
junit-4.10.jar
log4j-1.2.17.jar
shiro-all-1.2.3.jar
slf4j-api-1.7.7.jar
slf4j-log4j12-1.7.5.jar
2、新建shiro.ini
[user]
zhangsan=11111
3、新建java类
public class AuthenticationDemo{
public static void main(String args[]){
//1、创建SecurityManager工厂,读取相应的配置文件
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.imi");
//2、通过SecurityManager工厂获取SecurityManager的实例
SecurityManager securityManager = factory.getInstance();
//3、将SecurityManager对象设置到运行环境中
SecurityUtils.setSecurityManager(securityManager);
//4、通过SecurityUtils获取Subject
Subject subject = SecurityUtils.getSubject();
//5、假如登录的用户名 zhangsan 和密码 1111
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","1111");
//6、进行用户验证
subject.login(token);
//7、通过subject来判断用户是否通过验证
if(subject.isAuthenticated()){
System.out.println("用户登录成功");
}
}
}
该异常有几个子类,分别不同的异常情况:
a)DisabledAccountException账户失效异常
b)ExcessiveAttemptsException尝试次数过多
c)unknownAccountException用户不正确
d)ExpiredCredentialsException凭证过期异常
e)IncorrectCredentialsException凭证不正确
try{
//6、用户身份验证
subject.login(token);
//7、通过subject来判断用户是否通过验证
if(subject.isAuthenticated){
System.out.println("用户登录成功");
}
}catch(UnknownAccountException e){
System.out.println("用户或密码不正确");
}catch(IncorrectCredientialsException e){
System.out.println("用户或密码不正确");
}
shiro的执行流程
- 通过shiro的相关API,创建securityManager及获取Subject实例
- 封装token信息
- 通过subject.login(token)进行用户认证
- subject接收token,通过其实现类DelegatingSubject将token委托交付给SecurityManager来完成认证。SecurityManager是接口通过DefaultSecurityManager来完成相关的功能的。由DefaultSecurityManager中的login来完成认证过程。在login中调用了该类的authenticate()来完成认证。该方法是由AuthenticationSecurityManager来完成的。在该类的authenticate()中,通过调用authenticator(认证器)来完成认证工作。Authenticator是有其默认实现类ModularRealmAuthenticator来完成认证。通过ModularmAuthenticator中的doAuthenticate来获取Realms信息。如果是单realm直接将token和realm中的数据进行比较,判断是否认证成功。如果是多realm那么需要通过Authentication Strategy来解决。