Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。
Shiro主要提供的功能有Authentication(身份认证)、Authorization(权限认证)、Session Management(session管理)、Cryptography(加密)四个核心功能,同时还提供缓存、并行处理、remember me等辅助功能。下面针对四个主要功能依次进行介绍。
shiro三个核心组件:
1、subject:shiro认证实体,简单理解可以说就是最基本的用户名、密码等认证信息;但在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、手机号、邮箱地址等。它意味着“当前跟软件交互的东西”。
2、securityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
3、Reaml:域,Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。这些组件在接下来的博客中会一一介绍它的具体用处,此处可略过。
二、Shiro HelloWorld
又到了helloworld时间。在web应用中使用shiro
1、首先需引入shiro jar包:shiro-core和slf4j-log4j12日志处理jar
2、创建java web程序,进行shiro预处理操作,初始化
public class HelleWorld { public static void main(String[] args) { // 读取配置文件,初始化SecurityManager工厂 Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro.ini"); // 获取securityManager实例 SecurityManager securityManager=factory.getInstance(); // 把securityManager实例绑定到SecurityUtils SecurityUtils.setSecurityManager(securityManager); // 得到当前执行的用户 Subject currentUser=SecurityUtils.getSubject(); // 创建token令牌,用户名/密码 UsernamePasswordToken token=new UsernamePasswordToken("java1234", "12345"); try{ // 身份认证 currentUser.login(token); System.out.println("身份认证成功!"); }catch(AuthenticationException e){ e.printStackTrace(); System.out.println("身份认证失败!"); } // 退出 currentUser.logout(); } }
shiro.ini文件配置如下:
[users] java1234=123456 jack=123
使用shiro框架,首先读取ini配置文件,初始化SecurityManager工厂,然后创建securityManager实例,通过SecurityUtils类get当前subject实例,创建令牌,执行用户的login方法,传入令牌token参数,将subject用户信息与配置文件中的user信息比对,对当前用户进行身份认证。这也是使用shiro进行身份认证的最基础代码逻辑。
三、shiro Authentication
在第一个实例中已经使用到了shiro两个核心组件subject和securityManager,subject作为shiro的认证主体,主要包含了principals(身份,可以是邮箱、手机号等,用来标识用户登录信息的实体)和credentials(凭证,密码,数字证书等)两类信息。再直白一点:最基本常用的就是用户名、密码,分别是此处的principals和credentials。
1、shiro身份认证流程
首先通过读配置文件创建的subject传入token信息,shiro的securityManager进行整体管理,Authenticator实体通过认证策略读取安全数据,进行身份认证。这里的认证策略就涉及到Reaml,它就是shiro获取验证数据的数据源,可以有很多种例如jdbc reaml,或者在上面例子中直接自己写一个shiro.ini配置文件【textReaml】,user进行身份验证时就从这里对比用户信息与reaml中的信息是否一致进行验证。
这里认证策略的意思就是通过选择什么样的reaml域进行验证,如果使用JDBC reaml那认证策略就是JDBC。
这里po出一个shiro创建JDBC reaml的实例:
1、首先新建一个jdbc_reaml.ini文件。ps.如果代码中加载了这些ini配置文件,shiro便会进行解析。可以把它理解为类似于xml或者log.properties文件。
2、因为是jdbc数据源,所以需要引入数据库连接相关的jar:c3p0 、mysql-driver
3、补充jdbc_reaml.ini文件如下
[main] jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm dataSource=com.mchange.v2.c3p0.ComboPooledDataSource dataSource.driverClass=com.mysql.jdbc.Driver dataSource.jdbcUrl=jdbc:mysql://localhost:3306/db_shiro dataSource.user=root dataSource.password=123456 jdbcRealm.dataSource=$dataSource securityManager.realms=$jdbcRealm
通过查看源码不难发现,形如dataSource.jdbcUrl这些属性配置,在shiro源码中均添加了set方法,$符表示对象引用。例如最后一句,引用该jdbcReaml对象附给将securityManager的域,这就确定了上边图中authentication的认证策略为刚创建的jdbc_reaml。
4、编写java代码,加载该jdbc域文件,同样初始化工厂、创建subject对象,传入token信息,login验证。
public static void main(String[] args) { // 读取配置文件,初始化SecurityManager工厂 Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:jdbc_realm.ini"); // 获取securityManager实例 SecurityManager securityManager=factory.getInstance(); // 把securityManager实例绑定到SecurityUtils SecurityUtils.setSecurityManager(securityManager); // 得到当前执行的用户 Subject currentUser=SecurityUtils.getSubject(); // 创建token令牌,用户名/密码 UsernamePasswordToken token=new UsernamePasswordToken("java1234", "123456"); try{ // 身份认证 currentUser.login(token); System.out.println("身份认证成功!"); }catch(AuthenticationException e){ e.printStackTrace(); System.out.println("身份认证失败!"); } // 退出 currentUser.logout(); } }此时,运行java main方法,进行验证的数据源便是笔者本地创建的数据库,如果token信息与数据库表总userName和password数据一致,则该用户身份认证成功。一般token信息是通过前台数据传过来的,这里随便写了些测试数据。