简单概念
在上一章节,我们探讨了Filter的执行流程,接下来仔细分析用户的登陆流程。
先看看shiro官方给出的一张图:
再看几个简单概念
Subject:主体,代表了当前 “用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是 Subject,如网络爬虫,机器人等;即一个抽象概念;所有 Subject 都绑定到 SecurityManager,与 Subject 的所有交互都会委托给 SecurityManager;可以把 Subject 认为是一个门面;SecurityManager 才是实际的执行者;
SecurityManager:安全管理器;即所有与安全有关的操作都会与 SecurityManager 交互;且它管理着所有 Subject;可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互,如果学习过 SpringMVC,你可以把它看成 DispatcherServlet 前端控制器;
Realm:域,Shiro 从从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。
[图片上传中...(Authentication.png-3b5e8d-1563620187017-0)]
:身份认证 / 登录,验证用户是不是拥有相应的身份;Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
登陆流程
具体的登陆流程如下:
1.从FormAuthenticationFilter的executeLogin()方法开始,把post表单提交的用户名称和密码封装为token,调用subject.login(token);
2.调用AuthenticatingSecurityManager.authenticate() 会调用securityManage配置的authenticator的authenticate()方法;
3.AbstractAuthenticator是抽象类,具体的实现还是调用ModularRealmAuthenticator.doAuthenticate(),这个方法主要是判断当前配置的登陆realm是单个还是多个;
4.单个realms调用return doSingleRealmAuthentication();
多个realms调用return doMultiRealmAuthentication();
5.单个realm的doGetAuthenticationInfo(),由业务去实现根据用户名查询用户信息,也就是认证的基础流程。具体的认证密码流程统一是在realm的父类AuthenticatingRealm实现.
至此,整个认证流程已经结束。
实践记录
多realm的登陆多了一个流程就是需要根据配置的策略判断那种方式才算登陆成功。多realm常用于多种登陆方式。下面分别列出几种不同的认证策略:
1.AtLeastOneSuccessfulStrategy:至少一条满足的情况,返回所有 Realm 身份验证成功的认证信息,也就是权限。这是默认的策略;
2.FirstSuccessfulStrategy第一条满足的情况,只返回第一个 Realm 身份验证成功的认证信息;
3.AllSuccessfulStrategy所有 Realm 验证成功才算成功,且返回所有 Realm 身份验证成功的认证信息,如果有一个失败就失败了。多个realm登陆,在实践中极端经常需要在realm的doGetAuthenticationInfo认证方法中抛出业务异常,但是会被shiro内部消化,所以需要在ModularRealmAuthenticator的子类复写doMultiRealmAuthentication
参考
即刻学院:身份验证
apache shiro: Apache Shiro Authentication