Shiro-Authentication(身份验证)
Authentication
Authentication是指身份验证的过程:即在应用中能证明他就是他本人.一般需要提供身份标识信息例如:ID,用户名/密码等. 在Shiro中,用户需要提供Principals和Credentials给Shiro,从而来验证用户的身份.
Principals: 身份,即是Subject的标识属性,可以是任何东西,诸如用户名、邮箱等,唯一即可.一个主题可以有多个Principal,但是只有一个Primary principal一般是用户名/密码.Credentials: 证明/凭据,只有主体才知道的安全值,如密码/数字证书.
principal / credential 配对最常见的就是 用户名 / 密码 .
Demo
在实际研究Shiro身份认证流程之前,先搭建一个架子,进行简单的验证.
Maven构建
添加junit、common-logging以及shiro-core等依赖.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lcore.shiro_01</groupId>
<artifactId>shiro_01</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>0.2.23</version>
</dependency>
</dependencies>
</project>shiro配置文件ini方式(shiro.ini)
简洁起见,这里仅仅配置一个用户名/密码(principal/credential),其他使用shiro默认配置.
之后编写一个简单的测试用例,shiro最简单的身份认证demo就完成了,代码如下:
关于上述demo的执行过程,注释已经说得很明白了,需要提及的是,在调用subject.login()身份验证失败时,请捕获AuthenticationException或其子类,常见的如DisabledAccountException(禁用的账户)、LockedAccountException(锁定的账户)、UnknowAccountException(错误的账户)等,具体情况如下图:
身份认证流程
demo中可以简单的了解Shiro的认证过程,接下来从shiro内部体系结构了解其认证流程: 流程如下:
1、首先调用
Subject.login()方法进行登录,内部会委托给SecurityManager,调用之前需要通过SecurityUtils.setSecurityManager()设置. 2、SecurityManager委托给Authenticator进行身份验证,Authenticator才是真正的身份验证者,也可以扩展实现自己的Authenticator. 3、Authenticator可能会委托给相应的AuthenticationStrategy进行多Realm身份验证,默认为ModularRealmAuthenticator会调用AuthenticationStrategy进行多Realm身份验证. 4、Authenticator会把相应的token传入Realm,从Realm获取身份验证信息,可以配置多个Realm,将按照相应的顺序和策略进行访问,最后完成身份认证.
阅读源码内部的的流程还是比较复杂的,大致的时序图如下: 上述只是一个大致的流程,实际情况复杂的多.
Realm
Realm:安全数据源,用于获取安全数据(用户、角色、权限规则),shiro通过SecurityManager验证用户,必须通过Realm获取相应的用户进行比较以确定用户是否合法.同样也是通过Realm得到用户相应的角色/权限控制用户的访问权限.shiro默认提供的Realm如下图:
上述图中可以知道的是,如果我们实现自定义的Realm一般继承AuthorizingRealm(授权)即可,因为其继承了AuthenticationgRealm和CachingRealm实现了身份验证和缓存.主要实现:
IniRealm: [users]部分指定其用户名/密码及其角色,[roles]部分指定其角色,权限信息.demo中就是使用的此方式.JdbcRealm: 通过SQL查询相应的信息,其相应的sql可以查阅源码查看,也可以通过api进行自定义SQL.
仔细思考一下可以知道,在实际中我们一般不会使用shiro提供的Realm,前面也说了shiro不维护用户/权限,仅仅通过Realm进行注入.Shiro提供的Realm总归不够灵活,因此正如上述所说,一般我们通过继承AuthorizingRealm实现自定义的Realm(结合自身的dao层,获取安全数据). 接下来了解下Realm如何使用.
单Realm配置
1、 自定义Realm实现:
2、ini配置文件指定自定义的Realm
通过$name来引入之前定义好的realm 3、测试代码:
JDBC Realm
Shiro提供的JDBC Realm使用也是比较简单且较为灵活的,使用方法如下: 1、maven添加数据库驱动及druid连接池,参考上述pom.xml 2、建立测试数据库及数据表数据,建表:users、user_roles,roles_permissions,并且添加一个测试用户:
之前,也说过Shiro并不维护用户/权限,实际系统的表结构并不像上述的设计,只是shiro的jdbcRealm默认是上述的.不过没关系,我们可以通过相关的接口重新指定验证的SQL,后面会提及. 3、ini配置
1、变量名=全类名 会自动创建实例 2、变量名.属性=值 自动调用相应的setter方法进行赋值 3、$变量名 引用之前的一个对象实例
4、测试代码
测试代码和上面并无太大区别,主要是初始化SecurityManager使用的配置文件不同
多Realm配置
在进行多Realm配置之前,有必要了解下,shiro是如何进行验证的,在之前的shiro验证流程图中已经了解到Subject.login()会交由DefaultSecurityManager的Authenticator进行验证authenticate().Authenticator的职责是验证用户账号,是Shiro API中身份验证的核心入口点. 跟踪源码,Authenticator还有一个ModularRealmAuthenticator实现,实际上是它委托给多个(也可以是单个)Realm进行验证,多个Realm的验证规则通过AuthenticationStrategy接口指定,阅读源码可知道,ModularRealmAuthenticator构造器默认指定的是AtleastOneSuccessfulStrategy(只要有一个Realm验证成功即可),且返回所有验证成功的认证信息. 具体来说Shiro默认提供的验证规则有如下几个:
1、
FirstSuccessfulStrategy:只要有一个Realm验证成功即可,返回第一个Realm验证成功的信息,其余忽略. 2、AtLeastOneSuccessfulStrategy:只要有一个验证成功即可,返回所有验证成功的验证信息. 3、AllSuccessfulStrategy:所有Realm验证成功即可,返回所有验证成功的验证信息.
多Realm的配置也比较容易,ini配置如下:
SecurityManager会按照realms指定的顺序进行验证,如果不指定,则会按照声明的顺序进行验证.如果显示指定顺序,声明了但是没有指定的会被忽略.上述3个自定义的Realm和之前并无太大区别,可以调整其验证规则,用于测试Shiro提供的3中验证策略.之后根据如下代码获取验证信息:
Shiro同样可以实现自定义的验证策略,比如我们实现一个OnlyOneAuthenticatorStrategy(只有一个验证通过才验证通过)
1、 实现OnlyOneAuthenticatorStrategy:
根据策略,我们需要在每次验证之后,合并验证信息,只要验证信息不等于1(都没有通过/通过多于1次)即是验证失败.之后在ini配置文件中,手动指定验证策略即可 具体就不在测试了,到此,Shiro身份验证OVER了!
本文链接: http://kiritor.github.io/2015/09/28/shiro-Authentication/
Last updated
Was this helpful?