Shiro应用框架图
Shiro应用安全块 |
|
Authentication—(认证登录) |
Authorization—(授权) |
SessionManagement—(会话管理) |
Cryptography—(加密) |
Shiro安全领域关注点 |
|
Web Support (轻松保护web应用程序安全) |
Caching (缓存,保证安全快速操作手段) |
Concurrency (支持多线程并发的特性) |
Testing (支持单元测试和集成测试) |
“Run As” (在许可前提下:用户假设另一个用户身份) |
RememberMe 跨Session记录用户的身份(记住我功能) |
注:Shiro不会为用户维护权根,需要我们去设计和提供。然后通过相关的接口注入给
Shrio。
概念层
展示了shiro组件如何相互作用。
Subject : 主体,代表了一个守护进程的账户,守护任务,当前和软件交互的任何事件
ShiroSecurityManager: Subject绑定到ShiroSecurityManager,与Subject所有交互都委托给ShiroSecurityManager。Subject是面,ShiroSecurityManager是实际执行者。ShiroSecurityManager是安全管理器,Shiro的核心(类似前端控制器)
Realm: 可以把Realm看作是Shiro的数据源。ShiroSecurityManager要验证用户身份的话,要从Realm获取相应的用户角色、权限进行比较,确定用户身份是否合法。是否进行操作。
流程概括:
应用代码通过subject进行授权和认证,Subjcet委托给ShiroSecurityManager。
ShiroSecurityManager需要注入Realm。ShiroSecurityManager得到用户信息与操作。
Shiro核心框架图(Security Manager)
Authenticator :用户认证管理器。 处理用户登录逻辑。通过调用realm接口来判断用户身份。Piuggable Realms(如果系统中配置了多个realm,则需要使用ActiveDirectoryRealm,以便决定用户登录认证是成功还是失败。如:一个用户验证成功了,但是其它的都失败了,是算成功还是失败呢)
Authorizer:权限管理器,用户访问控制(用户能做什么,不能做什么,也知道协调多个Realm数据源)。
SessionManager:会话管理器。如何创建会话,会话的生命周期。如果当前环境有会话管理机制,则Shiro会默认使用该环境下的会话管理机制(如service容器)。
SessionDAO:允许用户使用任何的数据源存储Session数据,主要是代替SessionManager执行Session方面的增、删、改、查,引入到Session管理的基本框架中。
CacheManager:创建维护一些其它Shiro组件中用到的Cache实例,维护Cache实体中的生命周期。缓存用于存储从后端获取到的用户验证及权限控制方面的数据,来提高性能。在获取数据时,能调用后端接口从其它数据源获取。
Cryptography: Shiro加密技术。
认证方案流程图
流程如下:
1、首先调用Subject.login(token)进行登录,其会自动委托给Security Manager,调用之前必须通过SecurityUtils. setSecurityManager()设置;
2、SecurityManager负责真正的身份验证逻辑;它会委托给Authenticator进行身份验证;
3、Authenticator才是真正的身份验证者,Shiro API中核心的身份认证入口点,此处可以自定义插入自己的实现;
4、Authenticator可能会委托给相应的AuthenticationStrategy进行多Realm身份验证,默认ModularRealmAuthenticator会调用AuthenticationStrategy进行多Realm身份验证;
5、Authenticator会把相应的token传入Realm,从Realm获取身份验证信息,如果没有返回/抛出异常表示身份验证失败了。此处可以配置多个Realm,将按照相应的顺序及策略进行访问。
Shiro权限拦截机制
ProxiedFilterChain:Shiro拦截对servlet容器拦截系列进行了代理,即ShiroFilter在容器拦截之前,通过ProxiedFilterChain对servlet容器进行了代理。先执行shiro自已的拦截系列,再执行servlet容器的拦截系列,即原始的Filter
|
官方API: http://shiro.apache.org/static/1.2.3/apidocs/
中文拦截器API: https://blog.csdn.net/qq_32347977/article/details/51083896
1、NameableFilter
NameableFilter给Filter起个名字,如果没有设置默认就是FilterName;还记得之前的如authc吗?当我们组装拦截器链时会根据这个名字找到相应的拦截器实例;
2、OncePerRequestFilter
OncePerRequestFilter用于防止多次执行Filter的;也就是说一次请求只会走一次拦截器链;另外提供enabled属性,表示是否开启该拦截器实例,默认enabled=true表示开启,如果不想让某个拦截器工作,可以设置为false即可。
3、ShiroFilter
ShiroFilter是整个Shiro的入口点,用于拦截需要安全控制的请求进行处理,这个之前已经用过了。
4、AdviceFilter
AdviceFilter提供了AOP风格的支持,类似于SpringMVC中的Interceptor:preHandler:类似于AOP中的前置增强;在拦截器链执行之前执行;如果返回true则继续拦截器链;否则中断后续的拦截器链的执行直接返回;进行预处理(如基于表单的身份验证、授权)
postHandle:类似于AOP中的后置返回增强;在拦截器链执行完成后执行;进行后处理(如记录执行时间之类的);
afterCompletion:类似于AOP中的后置最终增强;即不管有没有异常都会执行;可以进行清理资源(如接触Subject与线程的绑定之类的);
5、PathMatchingFilter
PathMatchingFilter提供了基于Ant风格的请求路径匹配功能及拦截器参数解析的功能,如“roles[admin,user]”自动根据“,”分割解析到一个路径参数配置并绑定到相应的路径:
pathsMatch:该方法用于path与请求路径进行匹配的方法;如果匹配返回true;
onPreHandle:在preHandle中,当pathsMatch匹配一个路径后,会调用opPreHandler方法并将路径绑定参数配置传给mappedValue;然后可以在这个方法中进行一些验证(如角色授权),如果验证失败可以返回false中断流程;默认返回true;也就是说子类可以只实现onPreHandle即可,无须实现preHandle。如果没有path与请求路径匹配,默认是通过的(即preHandle返回true)。
6、AccessControlFilter
AccessControlFilter提供了访问控制的基础功能;比如是否允许访问/当访问拒绝时如何处理等:
isAccessAllowed:表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false;
onAccessDenied:表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。
onPreHandle会自动调用这两个方法决定是否继续处理:
Shiro会话管理
Shior会话管理不依赖底层容器,如web容器,tomcat容器,JAVA-ee,JAVAse都能使用。会话管理,会话事件监听,会话存储,持久化,集群,失效过期支持,对web透明支持,SSO单点登录等特性,Shiro的会话管理可以满足web的会话管理。
会话管理器,管理应用中所有的Subject会话,创建,维护,删除,验证的工作
顶层组件SecurityManager继承了SessionManager,它提供了ReamlSecurityManager的实现,直接把会话管理委托给了SessionSecurityManager、DefalutSecurityManager和DefaultWebSecurityManager默认都继承了SessionSecurityManager。Shiro提供了三套默认的Session的管理,分别是:DefaultWebSessionManager、DefaultSessionManager和ServletContainerSessionManager。
DefaultSessionManager是DefalutSecurityManager使用的默认实现,用于javase环境。
ServletContainerSessionManager使用默认实现是DefaultWebSecurityManager。用于web环境。
DefaultWebSessionManager用于web环境的实现。可以直接替代ServletContainerSessionManager。直接废弃了servlet容器的会话管理。
Shiro同时提供了会话验证调度器,定期维护用户名是否过期,如果过期将停止会话。处于性能考虑,一般情况下,获取会话时,去验证会话是否过期。但是如果在web环境中,用户不主动退出,不知道会话是否过期的,因此需要定期的检测会话。Shiro提供了验证调度器,SessionValidationScheduler就是做这样的事情。
CacheManager缓存管理器
CacheManager缓存控制器用于管理用户、角色、权限的缓存的,因为这些数据基本上很少去改变。放到缓存中可以提高访问的性能。
CacheManager的核心有三个接口,分别是:Cache接口、CacheManager接口、CacheManagerAware接口。
(打开Cache接口实现原码)包括:取数据、放数据、移除数据、清空cache等cache等相关的操作方法。它的实现有EhCache和MapCache。EhCache是现成的缓存组件。
而MapCache是在内存中缓存。由此可以看出来Shiro并没有提供现实完整的缓存组件。
Shiro提供了一个Cache接口底层缓存api。允许使用缓存组件如:redis、Ehcache等。
(打开CacheManager接口实现原码)发现只有一个方法getCaChe。根据名称获取一个Cache。
(打开CacheManagerAware接口实现原码)也只有一个方法setCacheManager用于注入CacheManager。
Shiro内部相应的组件DefaultSecurityManager自动检查相应的对象,比如Realm是否实现了CacheManagerAware这个接口,如果实现了就会自动注入CacheManager。
从这个类图可以看出来Shiro主要做了Realm缓存和Cache的缓存。
关于AuthorizingRealm的类图
AuthorizingRealm与AuthenticatingRealm分别提供了对AuthorizationInfo和AuthenticationInfo的信息缓存。
AuthenticationInfo:代表着主体subject存储的信息。主要存储的是登录认证。
AuthorizationInfo:代表着主体subject存储的信息。主要存储的是角色,权限以类的信息。用来做权限校验。
Shiro缓存主要与CacheManagerAware和SessionSecurityManager有关系,具体类图如下:
当我们设置SessionManager的时候,如果实现了SessionSecurityManager它会自动判断是否实现了CacheManagerAware接口。如果实现了自动会把ChcheManagerAware设置给CacheManager。然后SessionManager会判断SessionDAO是否实现了CacheManager这个接口。SessionDAO继承了CachingSessionDAO,如果实现了会把SessionManager设置给CacheManager