shiro功能:
处理身份认证、授权、企业会话管理和密码技术。
-
验证用户身份
-
用户访问控制(用户安全角色、允许的操作判别)
-
在没有 web 和 EJB 容器的情况下,在任何环境中使用 会话 API
-
在认证、访问控制或在会话的生命周期中对事件作出反应
-
将用户的安全数据聚合为 1 个或多个数据源并以单个可分解的用户视图呈现
-
能实现单点登录功能(Single Sign On)
-
能实现“记住我”服务,不用登录的用户联想
-
More …
应用安全的四大基石(Cornerstone)
-
Authentication(身份认证):提供用户存在的行为,例如登录;
-
Authorization(授权):访问控制的进程,例如决定谁有访问权限
-
Session Management(会话管理):管理特定用户的会话,即使在非 web 或 EJB 应用中
-
Cryptography(密码技术):在方便使用的同时,使用加密学算法保持数据安全
有许多额外的功能支持并加强在不同应用环境下的关注度
-
Web支持:Shiro的API帮助简单的使用web应用安全;
-
缓存:缓存在Shiro APIs中是重点(一线公民),确保安全操作快速和有效;
-
一致性:支持多线程应用;
-
测试:存在测试支持,帮助编写单元和集成测试,并确保代码能像预期的那样被保护;
-
运行方式:一个允许用户假定其他用户的身份(如果被允许)的功能,有时在管理方案中很有用;
-
记住我:通过Sessions记住用户的身份,所以只需要在强制登录时登录。
shiro安全框架中的术语
Authentication(认证):
验证用户是否合法,也就是登陆)
Authorization(授权):
(授予谁具有访问某些资源的权限)
Session Management(会话管理)
用户登陆后的用户信息通过session Management来进行管理,不管是在什么应用中
Cryptography (密码学):
学密码英文的一种通过隐藏或将信息转换分类照片照片什么中翻译无意义的方式来保护信息不受欢迎的行为,因此没有人可以阅读它.Shiro主要关注加密的两个核心元素:加密像电子邮件一样使用公钥或私钥加密密码,而散列(又名消息摘要)对像密码这样的数据进行不可逆转的加密。(提供了一些常见的加密算法,并且使用很便捷)
cache(缓存)
登陆授权这种东西,授权一次就OK了,但是对于权限的检查,权限检查每次都要去做,甚至权限检查,还要每次查询数据库,,四郎提供了对缓存的支持,通过缓存,我们直接从缓存里去取,效率就会提高很多。它支持多种缓存(redis的的的缓存数据库,ehcache的的的缓存)并发并发支持,支持多线程并发访问
- 委托人(用户标识,如用户名,学号...)
shiro的架构:
需要进行身份认证和授权的用户,应用,都称为主(主体),需要将身份和凭证信息都交给主题,主题再交给安全管理器,它再调用相应的授权器,认证器,这两个器再调用下一层的领域域.realms域用来和外界的数据源和数据库进行交互,从而获取外界所需要的数据.shiro只管安全,不维护数据,受试者获取服务器的数据,获取以后,四郎干活,取数据库,通过境界来匹配,境界会取相应数据源的信息进行匹配。
主题:(主体)
该主体可以是用户,第三方程序...主题用于获取主体的信息...
安全管理
四郎的核心,协调管理四郎各组件之间的工作
认证:(认证)
负责验证用户的生份
授权:(授权)
负责为合法用户授权
领域:
它可以获取数据库信息,文本信息,可有多个。
第二节:用户验证
校长用户的身份信息,受到的表示属性,如省份证号码,电话号码
- 凭据
凭证(就是密码)可以是密码,或数字证书
凭证用户名/密码需要将这两个交给四郎
流程:
token交给主题,----“securitymanager ----”Authenticator(认证)(根据配置的realm去调用策略)---“plugin realm(可插入的jdbc领域(缓存)...自定义境界(高速缓存))
编码:INI文件可以进行数据的分组。
身份认证:
代码结构:
引入shiro的依赖,self4j日志依赖,log4j的日志
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>shiro</groupId>
<artifactId>shiro</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/shiro-all-1.2.3.jar</systemPath>
</dependency>
<!--lib没有shiro架包时,可添加引入依赖
Shiro核心包 -->
<!-- <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>-->
<!-- 日志文件管理包 -->
<!-- log start,通过log4j.properties配置日志的打印格式 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--slf4j服务于各种日志系统,暴露很多日志接口,供第三方程序调用,进行日志输出-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
</dependencies>
AuthenticationDemo测试类
package cn.sxt.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.subject.Subject;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
public class AuthenticationDemo {
public static void main(String[] args){
//1.创建SecurityManager工厂,读取配置文件
Factory<SecurityManager> factory= new IniSecurityManagerFactory("classpath:shiro.ini");
//2.通过SecurityManager获取SecurityManager实例,添加到运行环境
SecurityManager securityManager=factory.getInstance();
//3.将SecurityManager设置到运行环境
SecurityUtils.setSecurityManager(securityManager);
//4.通过securityUtils获取主体Subject,获取到就能做事了
Subject subject=SecurityUtils.getSubject();
try {
//5.加入登陆的用户名,密码:张三/1111,shiro的张三,1111相当于数据里存放的信息
UsernamePasswordToken token = new UsernamePasswordToken("lisi", "1111");
//6.进行用户身份验证
subject.login(token);
//通过subject判断用户是否通过验证
if (subject.isAuthenticated()) {
System.out.println("用户登陆成功");
}else {System.out.println("用户名或密码不正确");}
}catch (AuthenticationException e){e.printStackTrace();
System.out.println("用户登录失败");
}
}
}
运行截图:
下面时异常处理:
AuthenticationException的子类有
DisableAccountException(账户失败异常)
ExceptionAttemptsException尝试次数过多
UnkonwAccountException用户不正确
ExpiredCredentialsException凭证过期
IncorrectCredentialsException凭证不正确
主题接收的令牌,通过实现类DelegatingSubject将令牌委托给安全管理器来完成认证,安全管理器是接口通过DelegatingSubject来完成相关功能,有DelegatingsecurityManager中登录来完成认证过程。再login中调用了类authenticate()来完成认证,该方法是authenticatingSecurityMangement来完成,由authenticator来完成认证工作,authenticator由默认实现类ModularRealmAuthenticator来完成,通过ModularRealmAuthenticator的doAuthenticate方法获取realm,单realm将token和realm中的数据进行比较,如果多realm需要Authentication strateg完成认证,subject.isAuthenticated()认证失败会抛出信息
jdbcReal及Authentication Strategy
shiro的认证,默认情况是iniRealm,如果需要使用别的realm,需要进行配置