Shiro

Shiro身份认证

2020-05-27  本文已影响0人  李白不喜欢杜甫

获取Subjects

1.获取认证数据或者证书

/Example using most common scenario of username/password pair:
UsernamePasswordToken token = new UsernamePasswordToken(username, password);

//"Remember Me" built-in: 
token.setRememberMe(true);
使用[UsernamePasswordToken](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authc/UsernamePasswordToken.html),它支持最常见的用户名/密码身份验证方法。这是Shiro的[org.apache.shiro.authc.AuthenticationToken](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authc/AuthenticationToken.html)接口的实现,该接口是Shiro的身份验证系统用来表示提交的主体和凭据的基本接口。
在此需要注意的重要一点是Shiro不在乎您如何获取此信息:数据可能是由提交HTML表单的用户获取的,或者是从HTTP标头中检索的,或者是从Swing或Flex中读取的GUI密码形式,或通过命令行参数。从应用程序最终用户收集信息的过程与Shiro的AuthenticationToken概念完全脱钩。

2.提交认证数据或凭证

Subject currentUser = SecurityUtils.getSubject();

currentUser.login(token);
在获取当前执行的之后`Subject`,我们进行一次[`login`](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/subject/Subject.html#login-org.apache.shiro.authc.AuthenticationToken-)调用,传入`AuthenticationToken`我们之前创建的实例。该`login`方法的调用有效地表示身份验证尝试。

3.认证成功或失败处理
如果该login方法安静地返回,就可以了-我们完成了!在Subject已经通过认证。应用程序线程可以不间断地继续运行,对的所有进一步调用SecurityUtils.getSubject()将返回已认证的Subject实例,对的任何调用都subject. isAuthenticated()将返回true
但是,如果登录尝试失败怎么办?例如,如果最终用户提供了错误的密码,或者访问了系统太多次并且可能他们的帐户被锁定了怎么办?
Shiro具有丰富的运行时AuthenticationException层次结构,可以准确说明尝试失败的原因。你可以用login一个try/catch块,赶上你想和作出相应的反应给他们任何异常。例如:

try {
    currentUser.login(token);
} catch ( UnknownAccountException uae ) { ...
} catch ( IncorrectCredentialsException ice ) { ...
} catch ( LockedAccountException lae ) { ...
} catch ( ExcessiveAttemptsException eae ) { ...
} ... catch your own ...
} catch ( AuthenticationException ae ) {
    //unexpected error?
}

//No problems, continue on as expected...
如果现有的异常类之一不能满足您的需求,AuthenticationExceptions则可以创建自定义来表示特定的故障情况。
[注意:尽管您的代码可以对特定的异常做出反应并在必要时执行逻辑,但是安全性最佳实践是仅在发生失败(例如,“用户名或密码不正确”)时向最终用户显示通用失败消息。这样可确保没有任何特定信息可供尝试攻击媒介的黑客使用。]

认证和记住的区别

如上面的例子所示,除了正常的登录过程之外,Shiro还支持“记住我”的概念。此时值得指出的是,Shiro非常精确地区分了记忆中的主题和实际经过验证的主题:

注销

认证的相反是释放所有已知的识别状态。当`Subject`完成与应用程序交互,你可以叫`subject.`[`logout()`]放弃所有的身份信息:
currentUser.logout(); //removes all identifying information and invalidates their session too.
当您调用时logout,任何现有的Session都将无效,并且所有身份都将被取消关联(例如,在Web应用程序中,RememberMe cookie也将被删除)。经过Subject日志出的Subject实例再次审议匿名的,并且,除了Web应用程序,可以重新使用login,如果需要的一次。
【注意:由于Web应用程序中记住的身份通常与cookie保持在一起,并且cookie只能在提交响应主体之前删除,因此强烈建议在调用后立即将最终用户重定向到新视图或页面subject.logout()。这保证了所有与安全性有关的cookie均会按预期删除。这是HTTP cookie的功能限制,而不是Shiro的限制。】

认证顺序

![image.png](https://img.haomeiwen.com/i8915236/add7687137632eff.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
1.应用程序代码调用该Subject.login方法,并传入AuthenticationToken表示最终用户的主体和凭据的构造实例。
2.`Subject`实例(通常是一个[`DelegatingSubject`](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/subject/support/DelegatingSubject.html)(或子类))`SecurityManager`通过调用来委托应用程序,实例`securityManager.login(token)`从此处开始实际的身份验证工作。
3. `SecurityManager`作为基本的“伞”组件,接收令牌并[`Authenticator`](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authc/Authenticator.html)通过调用来简单地委派给其内部实例[`authenticator.authenticate(token)`](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authc/Authenticator.html#authenticate-org.apache.shiro.authc.AuthenticationToken-)。这几乎总是一个[`ModularRealmAuthenticator`](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authc/pam/ModularRealmAuthenticator.html)实例,它支持`Realm`在身份验证期间协调一个或多个实例。在`ModularRealmAuthenticator`本质上提供一个[PAM](https://en.wikipedia.org/wiki/Pluggable_Authentication_Modules)为Apache四郎(其中每个样式的范例`Realm`是在PAM术语一个“模块”)。
4.如果`Realm`为该应用程序配置了多个,则该`ModularRealmAuthenticator`实例将`Realm`使用其configureed 发起多次身份验证尝试[`AuthenticationStrategy`](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authc/pam/AuthenticationStrategy.html)。在`Realms`调用进行身份验证之前,期间和之后,将调用,`AuthenticationStrategy`以允许它对每个Realm的结果做出反应。我们将`AuthenticationStrategies`尽快覆盖。
5.`Realm`请咨询每个配置,以查看是否[`supports`](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/realm/Realm.html#supports-org.apache.shiro.authc.AuthenticationToken-)已提交`AuthenticationToken`。如果是这样,支持的Realm [`getAuthenticationInfo`](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/realm/Realm.html#getAuthenticationInfo-org.apache.shiro.authc.AuthenticationToken-)方法将与Submitted一起调用`token`。该`getAuthenticationInfo`方法有效地表示针对该特定对象的单个身份验证尝试`Realm`。我们将`Realm`很快介绍身份验证行为。

认证器

如前所述,Shiro `SecurityManager`实现默认使用[`ModularRealmAuthenticator`](http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authc/pam/ModularRealmAuthenticator.html)实例。它们`ModularRealmAuthenticator`同样支持具有单个领域以及具有多个领域的应用程序。

在单一领域的应用程序中,ModularRealmAuthenticatorRealm直接调用单一领域。如果配置了两个或更多领域,它将使用一个AuthenticationStrategy实例来协调尝试的发生方式。我们将在下面介绍AuthenticationStrategies。

如果您希望SecurityManager使用自定义Authenticator实现来配置,则可以在shiro.ini以下示例中进行配置:(在Maven使用realm注入)

[main]
...
authenticator = com.foo.bar.CustomAuthenticator

securityManager.authenticator = $authenticator

领域认证

当程序配有多个数据源时,`ModularRealmAuthenticator`依赖于内部[`AuthenticationStrategy`]组件来确定认证尝试成功或失败的条件。

例如,如果只有一个Realm认证`AuthenticationToken`成功,而其他所有认证都失败,那么认证尝试是否被视为成功?还是必须所有领域都成功进行身份验证,才能将整体尝试视为成功?或者,如果某个领域成功通过身份验证,是否有必要进一步咨询其他领域?一种`AuthenticationStrategy`使基于应用程序的需要作出适当的决定。

AuthenticationStrategy是一个无状态组件,在身份验证尝试期间会被查询4次(这4种交互所需的任何必要状态都将作为方法参数给出):
    1.  在任何领域被调用之前
    2.  在`getAuthenticationInfo`调用单个Realm 方法之前
    3.  在`getAuthenticationInfo`调用单个领域的方法之后
    4.  在所有领域都被调用之后

另外,`AuthenticationStrategy`负责将每个成功Realm的结果汇总并“捆绑”为单个[`AuthenticationInfo`]表示形式。这个最终的聚合`AuthenticationInfo`实例是该`Authenticator`实例返回的内容,也是Shiro用来表示`Subject`的最终身份(又称为Principals)的东西。
Shiro有3种具体的AuthenticationStrategy实现方式:
![image.png](https://img.haomeiwen.com/i8915236/94f9e81c01eacc01.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
在ModularRealmAuthenticator默认的AtLeastOneSuccessfulStrategy实施,因为这是最常用的策略所需。但是,您可以根据需要配置其他策略:
```
  [main]
   authcStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategy
  securityManager.authenticator.authenticationStrategy = $authcStrategy

```
上一篇 下一篇

猜你喜欢

热点阅读