博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring security系列二:过滤器机制
阅读量:5947 次
发布时间:2019-06-19

本文共 4126 字,大约阅读时间需要 13 分钟。

spring security框架的过滤器是基于基础的filter来实现,这样它可以不需要依赖任何web框架,甚至连spring mvc框架都不需要依赖,这样整个spring security过滤器就会变得异常的轻量级和无侵入性。

spring security处理请求流程

clipboard.png

用户发起请求,认证管理器(Authentication Manager)会发起拦截,验证用户发起请求时的一些凭证信息,未通过验证信息审核的那么返回给用户,通过审核的,那么继续进行请求访问,访问页面之前,会被访问决策管理(Access Decision Manager)拦截,访问决策管理器验证用户是否有访问页面的权限,如果有,那么继续到访问页面。

另外spring security是通过委托代理(delegates)的方式去实现过滤器链的,

首先先通过过滤器拦截用户的请求,拦截后通过servlet来进行处理,如果处理成功那么进行正常访问,在返回给用户一个请求。

clipboard.png

spring security 内置拦截器顺序及用途

1、ChannelProcessingFilter,使用它因为我们可能会指向不同的协议(如:Http,Https)

2、SecurityContextPersistenceFilter,负责从SecurityContextRepository 获取或存储 SecurityContext。SecurityContext 代表了用户安全和认证过的session

3、ConcurrentSessionFilter,使用SecurityContextHolder的功能,更新来自“安全对象”不间断的请求,进而更新SessionRegistry

4、认证进行机制,UsernamePasswordAuthenticationFilter,CasAuthenticationFilter,BasicAuthenticationFilter等等--SecurityContextHolder可能会修改含有Authentication这样认证信息的token值

5、SecurityContextHolderAwareRequestFilter,如果你想用它的话,需要初始化spring security中的HttpServletRequestWrapper到你的servlet容器中。

6、JaasApiIntegrationFilter,如果JaasAuthenticationToken在SecurityContextHolder的上下文中,在过滤器链中JaasAuthenticationToken将作为一个对象。

7、RememberMeAuthenticationFilter,如果还没有新的认证程序机制更新SecurityContextHolder,并且请求已经被一个“记住我”的服务替代,那么将会有一个Authentication对象将存放到这(就是 已经作为cookie请求的内容)。

8、AnonymousAuthenticationFilter,如果没有任何认证程序机制更新SecurityContextHolder,一个匿名的对象将存放到这。

9、ExceptionTranslationFilter,为了捕获spring security的错误,所以一个http响应将返回一个Exception或是触发AuthenticationEntryPoint。

10、FilterSecurityInterceptor,当连接被拒绝时,保护web URLS并且抛出异常。

安全过滤器链

Spring Security维护了一个过滤器链,每个过滤器拥有特定的功能,过滤器需要服务也会对应添加和删除。 过滤器的次序是非常重要的,它们之间都有依赖关系。

DelegatingFilterProxy

当使用servlet过滤器时,你很需要在你的web.xml中声明它们, 它们可能被servlet容器忽略。在Spring Security,过滤器类也是定义在xml中的spring bean, 因此可以获得Spring的依赖注入机制和生命周期接口。 spring的DelegatingFilterProxy提供了在 web.xml和application context之间的联系。

当使用DelegatingFilterProxy,你会看到像 web.xml文件中的这样内容:

myFilter
org.springframework.web.filter.DelegatingFilterProxy
myFilter
/*

注意这个过滤器其实是一个DelegatingFilterProxy,这个过滤器里没有实现过滤器的任何逻辑。 DelegatingFilterProxy做的事情是代理Filter的方法,从application context里获得bean。 这让bean可以获得spring web application context的生命周期支持,使配置较为轻便。 bean必须实现javax.servlet.Filter接口,它必须和filter-name里定义的名称是一样的。

clipboard.png

FilterChainProxy

如果我们把所有的过滤器作为一个DelegatingFilterProxy入口添加到web.xml, 确认它们的次序是正确的。 这是一种繁琐的方式,会让web.xml显得十分杂乱,如果我们配置了太多过滤器的话。 我们最好添加一个单独的入口,在web.xml中,然后在application context中处理实体, 管理我们的web安全bean。 这就是FilterChainProxy所做的事情。它使用DelegatingFilterProxy (就像上面例子中那样),但是对应的class是org.springframework.security.web.FilterChainProxy。 过滤器链是在application context中声明的。这里有一个例子:

你可能注意到FilterSecurityInterceptor声明的不同方式。 命名空间元素filter-chain-map被用来设置安全过滤器链。 它映射一个特定的URL模式,到过滤器链中,从bean名称来定义的filters元素。 它同时支持正则表达式和ant路径,并且只使用第一个出现的匹配URI。 在运行阶段FilterChainProxy会定位当前web请求匹配的第一个URI模式,由filters属性指定的过滤器bean列表将开始处理请求。 过滤器会按照定义的顺序依次执行,所以你可以对处理特定URL的过滤器链进行完全的控制。

你可能注意到了,我们在过滤器链里声明了两个SecurityContextPersistenceFilter(ASC是allowSessionCreation的简写,是SecurityContextPersistenceFilter的一个属性)。 因为web服务从来不会在请求里带上jsessionid,为每个用户代理都创建一个HttpSession完全是一种浪费。 如果你需要构建一个高等级最高可扩展性的系统,我们推荐你使用上面的配置方法。 对于小一点儿的项目,使用一个HttpSessionContextIntegrationFilter(让它的allowSessionCreation默认为true)就足够了。

在有关声明周期的问题上,如果这些方法被FilterChainProxy自己调用,FilterChainProxy会始终根据下一层的Filter代理init(FilterConfig)和destroy()方法。 这时,FilterChainProxy会保证初始化和销毁操作只会在Filter上调用一次, 而不管它在过滤器链中被声明了多少次)。你控制着所有的抉择,比如这些方法是否被调用 或targetFilterLifecycle初始化参数DelegatingFilterProxy。 默认情况下,这个参数是false,servlet容器生命周期调用不会传播到 DelegatingFilterProxy。

当我们了解如何使用命名控制配置构建web安全。 我们使用一个DelegatingFilterProxy,它的名字是“springSecurityFilterChain”。 你应该现在可以看到FilterChainProxy的名字,它是由命名空间创建的。

clipboard.png

clipboard.png

自定义Filter

自定义Filter 建议继承 GenericFilterBean

clipboard.png

配置自定义 Filter 在 Spring Security 过滤器链中的位置

clipboard.png

HttpSecurity 有三个常用方法来配置:

  • addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter)在 beforeFilter 之前添加 filter
  • addFilterAfter(Filter filter, Class<? extends Filter> afterFilter)在 afterFilter 之后添filter
  • addFilterAt(Filter filter, Class<? extends Filter> atFilter)在 atFilter 相同位置添加 filter,此 filter 不覆盖 filter.

通过在不同 Filter 的 doFilter() 方法中加断点调试,可以判断哪个 filter 先执行,从而判断 filter 的执行顺序 。

转载地址:http://bebxx.baihongyu.com/

你可能感兴趣的文章
soapUI的简单使用(webservice接口功能测试)
查看>>
框架 Hibernate
查看>>
python-while循环
查看>>
手机端上传图片及java后台接收和ajaxForm提交
查看>>
【MSDN 目录】C#编程指南、C#教程、ASP.NET参考、ASP.NET 4、.NET Framework类库
查看>>
jquery 怎么触发select的change事件
查看>>
angularjs指令(二)
查看>>
<气场>读书笔记
查看>>
领域驱动设计,构建简单的新闻系统,20分钟够吗?
查看>>
web安全问题分析与防御总结
查看>>
React 组件通信之 React context
查看>>
Linux下通过配置Crontab实现进程守护
查看>>
ios 打包上传Appstore 时报的错误 90101 90149
查看>>
密码概述
查看>>
jQuery的技巧01
查看>>
基于泛型实现的ibatis通用分页查询
查看>>
gopacket 使用
查看>>
AlertDialog对话框
查看>>
我的友情链接
查看>>
linux安全---cacti+ntop监控
查看>>