filterchain(filterchaindofilter空指针)

http://www.itjxue.com  2023-02-24 16:10  来源:未知  点击次数: 

Spring Security解析三:SecurityFilterChain创建过程

从 Spring Security解析一:安全配置过程概览 章节我们知道了 springSecurityFilterChain 的大致构建过程,这里进步探讨其创建的细节。

springSecurityFilterChain的创建是关键,当创建完该Bean以后,再结合SpringBoot的自动化装配过程完成了在Servlet容器中注册,从而达到了对请求的拦截处理。

WebSecurity的作用就是构建springSecurityFilterChain,通过前面过程的配置,最后执行其buid()方法完成了构建过程。WebSecurity的继承关系如下:

WebSecurityConfiguration中完成springSecurityFilterChain的构建,如下所示:

接着进一步探究WebSecurity的build方法的执行细节。

在执行WebSecurity实例的build时,会调用父类AbstractConfiguredSecurityBuilder的doBuild()方法,该方法是个模板方法,定义如下:

从上到下,我们探究下init()与configure()方法都做了啥

我们以默认的WebSecurityConfigurerAdapter类分析这两个方法的内部实现,毕竟我们基本都是对该类进行扩展来对Spring Security进行定制配置。

最后我们看下与上面调用有关的WebSecurity中的方法

这里面的SecurityConfigurer类型的对象(默认是WebSecurityConfigurerAdapter)是构建SecurityFilterChain的关键,里面的init和configure方法更是完成装配的主要过程,在后面将会对WebSecurityConfigurerAdapter进行深入的分析。

Shiro中的filter

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 方法,验证用户是否登录过,如果验证未通过则跳转到登录页面

mina 源码解析(1)

mina是一款网络应用框架, 它是基于java nio 的 通讯框架, 提供抽象的事件驱动异步的api。

mina 基本架构:

大致上分为三层IoSerivce, Filter, Handler

首先我们来看一下Filter

前面说过, mina 是基于事件驱动的, 所以我们先来看一下mina定义了那些事件:

IoEventType 类中定义了如下枚举变量:

这些事件对于用户使用者来说无需关心。

以上IoEventType仅是事件的类型(事件的属性), mina对于事件是通过IoEvent对象进行封装的。

来看一下IoEvent 都有哪些方法:

我们看到IoEvent 实现了Runnable,也就是说这个对象会交给多线程去执行run方法。

在run方法中我们看到执行的是fire(), 也就是具体的任务了。

下面来看一下fire中做的事情, 首先看以下IoEvent 中 具体做了哪些事情, 再看一下其子类IoFilterEvent又做了哪些事情。 后面我会讲IoFilterEvent 的作用是什么, 在哪里用到。

其实做的事情就是触发(调用) session下filterchain的对应事件类型的方法。

IoFilterEvent 是IoEvent 的子类, 从名字就可以看出来, 其与IoFilter 有一定的关系, 所以IoFilterEvent是由IoFilter 产生的事件。

而IoFilter 产生的事件有什么特性呢?

在此插入IoFilter与IoFilterChain 的介绍。

IoFilter 是 拦截处理事件的过滤器, 如同servlet的filter。 它可以用于很多目的:

日志记录, 性能测量, 认证等等。

而filterchain 即代表一串IoFilter的链子, 其有多个IoFilter 组成。 事实上,在IoFilterChain 中,封装了一层Entry, 每个Entry中封装了当前的IoFilter和下一个IoFilter的引用。 可以看到Entry的接口如下

NextFilter 顾名思义, 即下一个IoFilter, 为什么需要有这么一个接口呢?

事实上, 我们可以想象, nextFilter 是用来 触发 下一个Iofilter的,其并不是IoFilter, 在IoFilter中, 我们可以看到这样的调用

说完了IoFilter, IoFilterChain, 那与IoFilterEvent有什么关系呢?

因为是IoFilter产生的事件, 当触发这个事件时, 由于链式的特征, 该事件将触发当前IoFilter 以后的Filter, 所以我们看到, IoFilter fire()的实现其实就是调用下一个filter的对应的事件方法:

也可以这样理解, 一个事件的产生, 产生地就是头, 事件从当前头向链后传播。

IoEvent 做的是从chain 的开头往后传播, IoFilterEvent是由当前IoFilter产生往后传播。

说完了IoFilter, 来探讨一下如何将IoFilter组装成IoFilterChain:

其实里面的结构就是链表。

来看看chain中add的内容:

(责任编辑:IT教学网)

更多

相关Javascript/Ajax文章

推荐Javascript/Ajax文章