shiro原理之过滤器

shiro原理之过滤器,第1张

这几天一直在研究Shiro到底是如何工作的,即一个请求过来了,它是如何做到知道这个请求应该用什么方式来鉴权的?应该调用哪个过滤器?自己定义的过滤器该如何才能生效?

带着这样的疑问,我做了一些测试与研究,并记录于此文。

Shiro对于请求的鉴权的实现也是通过过滤器(或者说是拦截器)来实现的,但是Spring项目中有拦截链机制,会有多个拦截器生效,包括系统内置的以及Shiro注入的,所以需要搞懂他的过滤的实现机制就需要去弄明白这些过滤器是如何过滤的。

在 ApplicationFilterChain 的 doFilter 方法下打上断点

默认过滤器

我们来看看 AbstractShiroFilter 的部分源码:

返回的是一个 ProxiedFilterChain 的实例,该实例包含了 PathMatchingFilterChainResolver 所匹配出来的过滤器,如下图,匹配的是系统内置的名为 anon 过滤器,至于它所对应的过滤器是什么可以见上面默认过滤器的表。

接着,在 AbstractShiroFilter 中的 executeChain 就会执行它的 doFilter 方法。

刚开始学习看源码,IDEA的调试工具也不是很会用,好在确实IDEA很强大,不然这么多过滤链跳来跳去是真的难懂。经过这次的阅读以及网上的博客的研究,Shiro的过滤链如果有自定义的过滤链的话,一定不能像平常的拦截器那样注入,必须要在注入 ShiroFilterFactoryBean 时使用如下方式注入才能生效。

因为很可能像平常注入过滤器那样注入先后顺序可能会存在问题。

DefaultFilter

shiro中提供的默认filter

FilterChainManager

通过配置创建对应的filterChain

Shiro通过此配置可初始化FilterChainManager中的filterChain,结构为 url ->filter列表

SpringShiroFilter

入口filter,拦截所有请求,通过请求的url匹配到对应的filterChain,然后通过Chain对请求进行,认证或者授权的处理

OncePerRequestFilter

OncePerRequestFilter 用于防止多次执行 Filter;也就是说一次请求只会走一次拦截器链;

另外提供 enabled 属性,表示是否开启该拦截器实例

实现了 doFilter 方法,提供了抽象方法 doFilterInternal

在doFilter中验证当前的Filter有没有执行过,如果已经执行过一次或者当前filter被禁用,则直接执行下一个Filter。如果没有执行过则执行 doFilterInternal 方法

AbstractShiroFilter

创建Subject,绑定subject到当前线程,根据url获取filterChain并执行filterChain

PathMatchingFilterChainResolver

通过请求的url来匹配FilterChainManager中的FilterChain,这个方法会返回一个 ProxiedFilterChain

ProxiedFilterChain

存储了tomcat的Filter 和shiro内部的filter

shiro内部的过滤器执行完后会切换到tomcat的过滤器继续执行

默认filter

除了LogoutFilter,其他都继承了AdviceFilter

AdviceFilter

AdviceFilter 提供了 AOP 风格的支持,类似于 SpringMVC 中的 Interceptor:

权限验证在preHandle中实现

PathMatchingFilter

PathMatchingFilter 提供了基于 Ant 风格的请求路径匹配功能及拦截器参数解析的功能,如

/admin roles[admin,user] ”自动根据 “,” 分割,解析成 /admin ->[admin,user] 存入 appliedPaths

实现了 preHandle 方法,通过请求的url匹配url对应的权限,解析权限串 调用子类的 onPreHandle 对权限进行处理

AnonymousFilter

提供匿名访问功能,实现了 onPreHandle 直接返回true,所以配置 anon 的url任何人都可以访问

AccessControlFilter

提供了资源访问控制的基础功能

实现了 onPreHandle ,这里拆分出了

isAccessAllowed (是否允许访问)和 onAccessDenied (访问被拒绝时)这两个方法供子类实现

AuthenticationFilter

实现了 isAccessAllowed 方法,验证用户是否已经登录,没有登录将被拒绝

FormAuthenticationFilter

继承自 AuthenticationFilter 只有用户登录过后才能通过

实现了 onAccessDenied 方法,如果请求的地址是登录地址,这里会尝试自动登录,否则跳转到登录页面

BasicHttpAuthenticationFilter

提供了基于 HttpBasic认证的方式

AuthorizationFilter

实现了 onAccessDenied 方法,如果没有认证通过,则跳转到登录或者认证失败的页面

PermissionsAuthorizationFilter

对用户所访问资源的权限进行认证

HttpMethodPermissionFilter

将HTTP请求的方法(例如GET、POST等)转换为相应的动作并构造一个相应的权限

如get 被转换为 read,put 转换为 update,post转换为create等

权限配置:/users perms[users]

请求: get /users

将会验证 用户是否拥有users:read权限

RolesAuthorizationFilter

验证用户是否用对对应的角色

UserFilter

实现了 isAccessAllowed onAccessDenied 方法,验证用户是否登录过,如果验证未通过则跳转到登录页面


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/bake/11856009.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-19
下一篇 2023-05-19

发表评论

登录后才能评论

评论列表(0条)

保存