转至:Elim的博客http://elim.iteye.com/blog/2161648

Filter Porxy

DelegatingFilterProxy

DelegationFilterProxy不是spring security的入口,它其实是spring的一个代理类(org.springframework.web.filter.DelegatingFilterProxy),作用是将spring 与 spring security融合。

它内部代理的是spring scurity的FilterChainProxy(org.springframework.security.web.FilterChainProxy)代理类。真正执行工作的是是FilterChainProxy。FilterChainProxy中会加载

所有的spring security filter,然后调用每个Filter的doFilter方法。targetFilterLifecycle初始化为true时,会调用所有filer的init初始化方法

详情查看https://www.cnblogs.com/hzhuxin/archive/2011/12/19/2293730.html

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value> <!-- 默认是false -->
</init-param>
</filter> <filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern> </filter-mapping>

FilterChainProxy

Spring security允许我们在配置文件中配置多个http元素,以针对不同形式的URL使用不同的安全控制。Spring Security将会为每一个http元素创建对应的FilterChain,同时按照它们的声明顺序加入到FilterChainProxy。所以当我们同时定义多个http元素时要确保将更具有特性的URL配置在前。

<security:http pattern="/login*.jsp*" security="none"/>

   <!-- http元素的pattern属性指定当前的http对应的FilterChain将匹配哪些URL,如未指定将匹配所有的请求 -->

   <security:http pattern="/admin/**">

      <security:intercept-url pattern="/**" access="ROLE_ADMIN"/>

   </security:http>

   <security:http>

      <security:intercept-url pattern="/**" access="ROLE_USER"/>

   </security:http>

需要注意的是http拥有一个匹配URL的pattern,未指定时表示匹配所有的请求,其下的子元素intercept-url也有一个匹配URL的pattern,该pattern是在http元素对应pattern基础上的,也就是说一个请求必须先满足http对应的pattern才有可能满足其下intercept-url对应的pattern。

Filter Chain中的Filer,按照先后顺序

  • ChannelProcessingFilter,如果你访问的channel错了,那首先就会在channel之间进行跳转,如http变为https。

  • SecurityContextPersistenceFilter,这样的话在一开始进行request的时候就可以在SecurityContextHolder中建立一个SecurityContext,然后在请求结束的时候,任何对SecurityContext的改变都可以被copy到HttpSession。

  • ConcurrentSessionFilter,因为它需要使用SecurityContextHolder的功能,而且更新对应session的最后更新时间,以及通过SessionRegistry获取当前的SessionInformation以检查当前的session是否已经过期,过期则会调用LogoutHandler。

  • 认证处理机制,如UsernamePasswordAuthenticationFilter,CasAuthenticationFilter,BasicAuthenticationFilter等,以至于SecurityContextHolder可以被更新为包含一个有效的Authentication请求。

  • SecurityContextHolderAwareRequestFilter,它将会把HttpServletRequest封装成一个继承自HttpServletRequestWrapper的SecurityContextHolderAwareRequestWrapper,同时使用SecurityContext实现了HttpServletRequest中与安全相关的方法。

  • JaasApiIntegrationFilter,如果SecurityContextHolder中拥有的Authentication是一个JaasAuthenticationToken,那么该Filter将使用包含在JaasAuthenticationToken中的Subject继续执行FilterChain。

  • RememberMeAuthenticationFilter,如果之前的认证处理机制没有更新SecurityContextHolder,并且用户请求包含了一个Remember-Me对应的cookie,那么一个对应的Authentication将会设给SecurityContextHolder。

  • AnonymousAuthenticationFilter,如果之前的认证机制都没有更新SecurityContextHolder拥有的Authentication,那么一个AnonymousAuthenticationToken将会设给SecurityContextHolder。

  • ExceptionTransactionFilter,用于处理在FilterChain范围内抛出的AccessDeniedException和AuthenticationException,并把它们转换为对应的Http错误码返回或者对应的页面。

  • FilterSecurityInterceptor,保护Web URI,并且在访问被拒绝时抛出异常。

自定义Filter,并添加到FilterChain

使用NameSpace时添加Filter到FilterChain是通过http元素下的custom-filter元素来定义的。定义custom-filter时需要我们通过ref属性指定其对应关联的是哪个Filter,此外还需要通过position、before或者after指定该Filter放置的位置。eg:position=”CAS_FILTER”就表示将定义的Filter放在CAS_FILTER对应的那个位置

Filter别名

别名 Filter类 对应元素或属性
CHANNEL_FILTER ChannelProcessingFilter http/intercept-url@requires-channe
SECURITY_CONTEXT_FILTER SecurityContextPersistenceFilter http
CONCURRENT_SESSION_FILTER ConcurrentSessionFilter http/session-management/concurrency-control
LOGOUT_FILTER LogoutFilter http/logout
X509_FILTER X509AuthenticationFilter http/x509
PRE_AUTH_FILTER AstractPreAuthenticatedProcessingFilter 的子类
CAS_FILTER CasAuthenticationFilter
FORM_LOGIN_FILTER UsernamePasswordAuthenticationFilter http/form-login
BASIC_AUTH_FILTER BasicAuthenticationFilter http/http-basic
SERVLET_API_SUPPORT_FILTER SecurityContextHolderAwareRequestFilter http@servlet-api-provision
JAAS_API_SUPPORT_FILTER JaasApiIntegrationFilter http@jaas-api-provision
REMEMBER_ME_FILTER RememberMeAuthenticationFilter http/remember-me
ANONYMOUS_FILTER AnonymousAuthenticationFilter http/anonymous
SESSION_MANAGEMENT_FILTER SessionManagementFilter http/session-managemen
EXCEPTION_TRANSLATION_FILTER ExceptionTranslationFilter http
FILTER_SECURITY_INTERCEPTOR FilterSecurityInterceptor http
SWITCH_USER_FILTER SwitchUserFilter

Spring Security定义好的核心Filter

FilterSecurityInterceptor

FilterSecurityInterceptor是用于保护Http资源的,它需要一个AccessDecisionManager和一个AuthenticationManager的引用。它会从SecurityContextHolder获取Authentication,然后通过SecurityMetadataSource可以得知当前请求是否在请求受保护的资源。对于请求那些受保护的资源,如果Authentication.isAuthenticated()返回false或者FilterSecurityInterceptor的alwaysReauthenticate属性为true,那么将会使用其引用的AuthenticationManager再认证一次,认证之后再使用认证后的Authentication替换SecurityContextHolder中拥有的那个。然后就是利用AccessDecisionManager进行权限的检查。

我们在使用基于NameSpace的配置时所配置的intercept-url就会跟FilterChain内部的FilterSecurityInterceptor绑定。如果要自己定义FilterSecurityInterceptor对应的bean,那么该bean定义大致如下所示:

<bean id="filterSecurityInterceptor"

   class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">

      <property name="authenticationManager" ref="authenticationManager" />

      <property name="accessDecisionManager" ref="accessDecisionManager" />

      <property name="securityMetadataSource">

         <security:filter-security-metadata-source>

            <security:intercept-url pattern="/admin/**" access="ROLE_ADMIN" />

            <security:intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN" />

         </security:filter-security-metadata-source>

      </property>

   </bean>

filter-security-metadata-source用于配置其securityMetadataSource属性。intercept-url用于配置需要拦截的URL与对应的权限关系。

ExceptionTranslationFilter

通过前面的介绍我们知道在Spring Security的Filter链表中ExceptionTranslationFilter就放在FilterSecurityInterceptor的前面。而ExceptionTranslationFilter是捕获来自FilterChain的异常,并对这些异常做处理。ExceptionTranslationFilter能够捕获来自FilterChain所有的异常,但是它只会处理两类异常,AuthenticationException和AccessDeniedException,其它的异常它会继续抛出。如果捕获到的是AuthenticationException,那么将会使用其对应的AuthenticationEntryPoint的commence()处理。如果捕获的异常是一个AccessDeniedException,那么将视当前访问的用户是否已经登录认证做不同的处理,如果未登录,则会使用关联的AuthenticationEntryPoint的commence()方法进行处理,否则将使用关联的AccessDeniedHandler的handle()方法进行处理。

AuthenticationEntryPoint是在用户没有登录时用于引导用户进行登录认证的,在实际应用中应根据具体的认证机制选择对应的AuthenticationEntryPoint。

AccessDeniedHandler用于在用户已经登录了,但是访问了其自身没有权限的资源时做出对应的处理。ExceptionTranslationFilter拥有的AccessDeniedHandler默认是AccessDeniedHandlerImpl,其会返回一个403错误码到客户端。我们可以通过显示的配置AccessDeniedHandlerImpl,同时给其指定一个errorPage使其可以返回对应的错误页面。当然我们也可以实现自己的AccessDeniedHandler。

<bean id="exceptionTranslationFilter"
class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp" />
</bean>
</property>
<property name="accessDeniedHandler">
<bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage" value="/access_denied.jsp" />
</bean>
</property>
</bean>

在上述配置中我们指定了AccessDeniedHandler为AccessDeniedHandlerImpl,同时为其指定了errorPage,这样发生AccessDeniedException后将转到对应的errorPage上。指定了AuthenticationEntryPoint为使用表单登录的LoginUrlAuthenticationEntryPoint。此外,需要注意的是如果该filter是作为自定义filter加入到由NameSpace自动建立的FilterChain中时需把它放在内置的ExceptionTranslationFilter后面,否则异常都将被内置的ExceptionTranslationFilter所捕获。

Spring Security 04的更多相关文章

  1. Spring Security(04)——认证简介

    目录 1.1     认证过程 1.2     Web应用的认证过程 1.2.1    ExceptionTranslationFilter 1.2.2    在request之间共享Security ...

  2. Spring Security 3.2.x与Spring 4.0.x的Maven依赖管理

    原文链接: Spring Security with Maven原文日期: 2013年04月24日翻译日期: 2014年06月29日翻译人员: 铁锚 1. 概述 本文通过实例为您介绍怎样使用 Mave ...

  3. Spring Security(19)——对Acl的支持

    目录 1.1           准备工作 1.2           表功能介绍 1.2.1     表acl_sid 1.2.2     表acl_class 1.2.3     表acl_obj ...

  4. Spring Security教程系列(一)基础篇-2

    第 4 章 自定义登陆页面 Spring Security虽然默认提供了一个登陆页面,但是这个页面实在太简陋了,只有在快速演示时才有可能它做系统的登陆页面,实际开发时无论是从美观还是实用性角度考虑,我 ...

  5. Spring security oauth2 client_credentials认证 最简单示例代码

    基于spring-boot-2.0.0 1,在pom.xml中添加: <!-- security --> <!-- https://mvnrepository.com/artifac ...

  6. 关于 Spring Security OAuth2 中 CORS 跨域问题

    CORS 是一个 W3C 标准,全称是”跨域资源共享”(Cross-origin resource sharing).它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了 AJA ...

  7. 朱晔和你聊Spring系列S1E10:强大且复杂的Spring Security(含OAuth2三角色+三模式完整例子)

    Spring Security功能多,组件抽象程度高,配置方式多样,导致了Spring Security强大且复杂的特性.Spring Security的学习成本几乎是Spring家族中最高的,Spr ...

  8. 转 - spring security oauth2 password授权模式

    原贴地址: https://segmentfault.com/a/1190000012260914#articleHeader6 序 前面的一篇文章讲了spring security oauth2的c ...

  9. Spring Security 使用数据库用户进行认证

    本文参考或摘录自:http://haohaoxuexi.iteye.com/blog/2157769 本文使用Spring Security自带的方式连接数据库对用户进行认证. 1.Spring Se ...

随机推荐

  1. MongoDB的使用学习之(二)简介

    原文链接:http://www.cnblogs.com/yxlblogs/p/3681089.html MongoDB 是一个高性能,开源,无模式的文档型数据库,是当前 NoSQL 数据库产品中最热门 ...

  2. Oracle package demo 包

    1.package 程序包说明(由函数.过程.变量.常量.游标和异常组成) create or replace package pk_test is -- Author : CHEN -- Creat ...

  3. 洛谷 P2783 有机化学之神偶尔会做作弊(Tarjan,LCA)

    题目背景 LS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. “第1354题怎么做”<--手语 他问道 ...

  4. 通过反射获取方法的参数名称(JDK8以上支持)

    方法的参数名,在很多时候我们是需要反射得到的.但是在java8之前,代码编译为class文件后,方法参数的类型是固定的,但参数名称却丢失了,这和动态语言严重依赖参数名称形成了鲜明对比.(java是静态 ...

  5. 网络安全专家教你设置史上最安全的WiFi密码

    通过设置强密码可以防止WiFi被蹭网现象的发生,保证WiFi网络安全.那么我们的WiFi密码怎么设置才最安全呢? 提供以下设置建议: 1.WiFi密码设置尽量使用字母.数字和字符组成的密码.这种密码强 ...

  6. flask之注册功能

    一:注册功能 1:前端准备表单 # 前端代码 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  7. SpringBoot之Web进阶

    .. 另外包括Springboot常用技术整合  以及项目上的应用

  8. pypi 清华镜像使用帮助

    清华镜像 地址 https://mirrors.tuna.tsinghua.edu.cn/help/pypi/ 临时使用 pip install -i https://pypi.tuna.tsingh ...

  9. 【Java】ApplicationContext应用上下文工具类

    @Slf4j @Service public class SpringContextHolder implements ApplicationContextAware, DisposableBean ...

  10. 【HDOJ6616】Divide the Stones(构造)

    题意:给定n堆石子,第i堆的个数为i,要求构造出一种方案将其分成k堆,使得这k堆每堆数量之和相等且堆数相等 保证k是n的一个约数 n<=1e5 思路:先把非法的情况判掉 n/k为偶数的方法及其简 ...