三,shiro核心(1)

来源:互联网 发布:淘宝优惠券卖家发放 编辑:程序博客网 时间:2024/04/28 04:06

1,Shiro认证

认证是一个身份识别的过程,也就是能够真是地证明使用者是谁说什么。对于一个用户证明他们的身份,他们需要提供一些识别信息和一些你的系统能够理解和相信的身份证据。

  • Principals:一个主体的识别属性,Principals可以使类似于firstName,lastName,userName,社工号等能够识别一个主体信息的字符信息。最好的Principals对于一个应用而言应该是唯一的。
  • Credentials:仅被主体知晓的秘密信息。通常的证书是密码,生物数据例如指纹和视网膜

1.1,认证主体

认证一个主体的过程可以分解成三个不同的步骤:

      1:收集主体提交的principals和credentials
      2:提交主体身份的principals和credentials
      3:如果提交成功,允许访问,要不然重复操作或者冻结账户

第一步:收集主体提交的principals和credentials

//创建用户绑定令牌UsernamePasswordToken token = new UsernamePasswordToken("jiang","123456");//记住用户登录信息token.setRememberMe(true);

第二步:提交主体身份的principals和credentials

Subject currentUser = SecurityUtils.getSubject();currentUser.login(token);

第二步:处理执行成功或失败

try {    currentUser.login(token);} catch ( UnknownAccountException uae ) { } catch ( IncorrectCredentialsException ice ) { } catch ( LockedAccountException lae ) { } catch ( ExcessiveAttemptsException eae ) { } } catch ( AuthenticationException ae ) {}

如果现有的异常类不能满足你的需求,自定义的AuthenticationExceptions可以呈现出具体的失败的场景

1.2,记住我VS认证

  • Remembered:被记住的主体不是匿名的,拥有可识别的身份。在上次的会话期间,身份是在之前的认证中被记住。subject.isRemembered() 返回true说明该主体身份被记住
  • Authenticated:在主体当前会话中,一个被认证的主体是被认证成功的主体。如果subject.isAuthenticated()返回true说明该主体是被认证成功的。

1.3,登出

currentUser.logout();

当用户登出是,当前存在的会话将是无效的,任何的身份验证信息也与应用程序分离

1.4,身份认证流程

这里写图片描述
第一步:应用程序执行Subject.login方法,传入构造AuthenticationToken实例代表最终用户的主体和凭证。
第二步:Subject实例,通常应用的SecurityManager的委托DelegatingSubject调用securityManager.login(token),认证过程开始。
第三步: SubjectManager 作为一个基本的“保护伞”的组成部分,接收 token 以及简单地委托给内部的Authenticator 实例通过调用 authenticator.authenticate(token)。这个通常是在认证的过程中支持协调一个或多个Realm实例的ModularRealmAuthenticator。ModularRealmAuthenticator本质上提供了PAM-style的范例(PAM是sun公司提出的一种认证模式,Pluggable Authentication Modules,可插拔认证模块)
第四步: 如果有多个的Realm配置在应用程序中,ModularRealmAuthenticator实例将会初始化一个多Realm认证去尝试获取它配置的AuthenticationStrategy。在 Realms 被身份验证调用之前,期间和以后,AuthenticationStrategy 被调用使其能够对每个 Realm 的结果作出反应。
单个Realm应用程序
如果应用程序中只有一个配置的Realm,这个将会被直接调用,没有必要使用AuthenticationStrategy

第五步: 每一个配置的Realm都会质询查看是否支持提交的AuthenticationToken,如果支持,那么Realm的getAuthenticationInfo方法将会被提交的token调用。getAuthenticationInfo方法有效的代表了一个单独的认证尝试获得特定的Realm。

1.4.1,认证器

Shiro SecurityManager 的实现默认使用一个 ModularRealmAuthenticator 实例。ModularRealmAuthenticator 同样支持单一的 Realm 以及那些多个 Realm 的应用。在一个单一的 Realm 应用中, ModularRealmAuthenticator 将直接调用这个单一的 Realm。如果有两个或两个以上的 Realm 配置,它将使用 AuthenticationStrategy 实例来调整这些尝试如何出现。
如果想通过自定义的Authenticator实现配置SecurityManager,可以在shiro.ini的配置文件中这么做:

[main]authenticator = com.foo.bar.CustomAuthenticatorsecurityManager.authenticator = $authenticator

1.4.2,认证策略

如果应用程序配置两个或两个以上的Realm时,ModularRealmAuthenticator依靠内部的AuthenticationStrategy组件来确定这些认证尝试的成功或失败的条件。
AuthenticationStrategy 是一个无状态的组件,它在身份验证尝试中被询问 4 次(这 4 次交互所需的任何必要的状态将被作为方法参数):

      1. 在任何 Realm 被调用之前被询问;
      2. 在一个单独的 Realm 的 getAuthenticationInfo 方法被调用之前立即被询问;
      3. 在一个单独的 Realm 的 getAuthenticationInfo 方法被调用之后立即被询问;
      4. 在所有的 Realm 被调用后询问。

另外, AuthenticationStrategy 负责从每一个成功的 Realm 汇总结果并将它们“捆绑”到一个单一的AuthenticationInfo 再现。这最后汇总的 AuthenticationInfo 实例就是从 Authenticator 实例返回的值以及 Shiro所用来代表 Subject 的最终身份 ID 的值(即 Principals(身份))。
3个具体的AuthenticationStrategy实现类

AuthenticationStrategy Class 描述 AtLeastOneSuccessfulStrategy 如果一个(或更多) Realm 验证成功,则整体的尝试被认为是成功的。如果没有一个验证成功,则整体尝试失败。 FirstSuccessfulStrategy 只有第一个成功地验证的 Realm 返回的信息将被使用。所有进一步的 Realm 将被忽略。如果没有一个验证成功,则整体尝试失败。 AllSucessfulStrategy 为了整体的尝试成功,所有配置的 Realm 必须验证成功。如果没有一个验证成功,则整体尝试失败

在shiro.ini文件中配置如下

[main]authcStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategyseurityManager.authenticator.authenticationStrategy = $authcStrategy

1.5,Realm的认证顺序

ModularRealmAuthenticator 将与 Realm 实例以迭代的顺序进行交互。

1.5.1,隐式排列

在shiro.ini文件中定义如下

blahRealm = com.company.blah.RealmfooRealm = com.company.foo.RealmbarRealm = com.company.another.Realm

SecurityManager 根据这三个 Realm 来配置,在认证尝试期间, blahRealm, fooRealm 和 barRealm 将按照上面那个顺序调用。使用这种方法,你并不需要设置 SecurityManager 的 Realm 属性——每个定义好的 realm 将会自动地被添加到realm 的属性。

1.5.2,显示排列

blahRealm = com.company.blah.RealmfooRealm = com.company.foo.RealmbarRealm = com.company.another.RealmsecurityManager.realms = $fooRealm, $barRealm

当你显式地配置 securityManager.realms 的属性是,只有已引用的 Realm 将会在
SecurityManager 中被配置。这意味着你能够在 INI 文件中定义 3 个 realm,但是实际上只能使用 2个如果只有这 2个被引用到 realm 的属性中的话.这是和隐式 realm 顺序不同的,所有可用的隐式的 realm 都将被使用。

0 0
原创粉丝点击