概述
本篇是对Shiro体系架构的介绍,本栏目大部分内容来自于Shiro官网。翻译过程中已经尽量保证用词的准确性和易懂性,如有不准确或者不确切的地方,请联系作者加以修改。本篇内容翻译自Authentication特征与Authentication官方指南。
Authentication是身份验证的过程,即证明该用户是否合法,对于证明一个用户是否合法,用户需要提供一些身份识别信息,以及系统能信任的身份证明,比如:用户名和密码等。下面我们先介绍一下Authentication中会遇到的术语和Authentication的特征:
Authentication术语:
- principles:身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。 一个主体可以有多个 principals,但只有一个 Primary principals,一般是用户名/密码/手机号。
- credentials:证明/凭证,即只有主体知道的安全值,如密码/数字证书等。 最常见的 principals 和 credentials 组合就是用户名/密码了。接下来先进行一个基本的身份认 证。
Authentication特征:
- 基于Subject:您在Shiro中所做的几乎所有操作都基于当前正在执行的用户,即Subject,而且您可以很容易在代码中的任何位置检索主题。
- 单一方法调用:身份验证过程只需要调用一个方法,即login(token)方法。只需要调用一个方法,API保持简单,并使您的应用程序代码干净,节省您的时间和精力。
- 多层次异常:Shiro提供了丰富的异常,以提供有关登录失败原因的详细说明。该设计可以更轻松地诊断与身份验证有关的代码错误或客户服务问题。此外,还可以帮助您根据需要创建更复杂的身份验证功能。
- 内置Remember Me功能:Remember Me功能为用户提供更好的用户体验。
- 可插拔数据源:Shiro使用使用Realms的可插拔数据访问对象(DAO)连接到LDAP和Active Directory安全数据源。并且提供了IniRealm、JdbcRealm等实现。开发人员也可以实现自定义Realm作为安全数据源。
- 可以使用一个或者多个Realms登录:Shiro可以同时使用一个或多个Realm对用户进行身份验证,并返回其身份的统一视图。另外,还可以使用Shiro的身份验证策略概念来自定义身份验证过程。可以在配置文件中设置策略,因此更改无需修改源代码,从而减少了复杂性和维护工作。
Authentication身份验证流程:
通过前面两篇的介绍我们已经知道应用程序只需要与Subject接口进行交互,那么Subject是如何进行身份验证的呢?如果只看代码的话会觉得非常简单,Subject接口有一个login方法,我们只需要调用该方法,即完成了对身份的认证。该方法定义如下:
void login(AuthenticationToken token) throws AuthenticationException;
如果身份验证失败时抛出AuthenticationException异常。而所传参数AuthenticationToken,该接口为身份验证信息的一个封装。我们可以使用其实现类UsernamePasswordToken收集验证信息。该类拥有四个参数用于收集需要验证的信息分别为username,password,host,rememberMe。如果觉得该实现类不能实现所需要的功能,也可以自定义实现AuthenticationToken。如下代码为UsernamePasswordToken的一个例子:
UsernamePasswordToken upt = new UsernamePasswordToken("pharos", "123456");
收集到用户凭证信息之后,可以调用login方法进行验证,我们通过SecurityUtils获取一个Subject实例。如下代码所示:
Subject subject = SecurityUtils.getSubject();
try {
UsernamePasswordToken upt = new UsernamePasswordToken("pharos", "123456");
subject.login(upt);
System.out.println("认证成功");
} catch (AuthenticationException e) {
System.out.println("认证失败");
}
之后的流程就可以交给SecurityManager去处理了。SecurityUtils也是架起SecurityManager接口和Subject接口的桥梁,我们可以通过SecurityUtils设置一个SecurityManager,代码如下,使用Shiro默认的Realm初始化一个SecurityManager。之后SecurityManager会根据IniRealm配置的数据进行身份验证。
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-starter.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
到目前为止,我们了解了如何使用Subject
在应用程序代码中对用户进行身份验证。现在,我们将介绍发生身份验证尝试时Shiro内部发生的情况。如下图为Authentication流程:
步骤1:应用程序代码调用Subject.login方法,并传入AuthenticationToken实例表示最终用户的principles和ccredentials。
第2步:Subject实例(通常是一个DelegatingSubject(或子类))通过调用SecurityManager.login(token)来委托给SecurityManager去处理,实例从此处开始实际的身份验证工作。
步骤3:SecurityManager作为基础组件,接收token并通过调用authenticator.authenticate(token)委派给其内部的Authenticator实例。这一般是一个ModularRealmAuthenticator实例,它在身份验证期间协调一个或多个Realm实例。
步骤4:如果为该应用程序配置了多个Realm,则该ModularRealmAuthenticator实例将根据配置的AuthenticationStrategy初始化Realm进行身份验证。在调用Realms进行身份验证之前,期间和之后,将调用AuthenticationStrategy以对每个Realm的结果做出反应。
第5步:查询配置每个的Realm,以查看它是否支持提交的AuthenticationToken。如果是,则将使用提交的token调用支持Realm的getAuthenticationInfo方法。getAuthenticationInfo方法代表Realm对身份进行验证。后续会详细介绍Realm是如何对身份进行验证的。
如下为Shiro身份验证的入门代码以及注释,该案例是使用application应用,SecurityUtils是将Subject联系起来的桥梁。在web中和集成Spring时,会使用其他方式初始化SecurityManager,后续介绍Web集成时会介绍。
public class AuthenticationStarter {
public static void main(String[] args) {
//初始化一个SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-starter.ini");
//获取SecurityManager
SecurityManager securityManager = factory.getInstance();
//使用SecurityUtils设置SecurityManager
SecurityUtils.setSecurityManager(securityManager);
//获取Subject
Subject subject = SecurityUtils.getSubject();
try {
//手机身份验证信息 用户名和密码
UsernamePasswordToken upt = new UsernamePasswordToken("pharos", "123456");
//登录
subject.login(upt);
System.out.println("认证成功");
} catch (AuthenticationException e) {
//登录失败,捕获异常
System.out.println("认证失败");
}
}
}
最后
以上就是稳重胡萝卜为你收集整理的Authentication—身份验证流程的全部内容,希望文章能够帮你解决Authentication—身份验证流程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复