转至: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. CentOS7搭建Kafka单机环境及基础操作

    前提 安装Kafka前需要先安装zookeeper集群,集体安装方法请参照我的另一篇文档. Kafka安装 下载 wget https://archive.apache.org/dist/kafka/ ...

  2. linux--mongodb安装与配置

    linux下的mongodb的安装: 在mongodb的官网上下载:mongodb-linux-x86_64-rhel62-3.2.3.gz1.解压: tar -xvf mongodb-linux-x ...

  3. 【学习】004 java并发包

    并发包[jdk1.7] 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问.数组的缺点是每个元素之间不 ...

  4. [apache] apache配置文件中的deny和allow

    allow 和Deny可以用于apache的conf文件或者.htaccess文件中(配合Directory, Location, Files等),用来控制目录和文件的访问授权. 例如: <Di ...

  5. MySQL重复数据中限定操作n条

    对于一个表,有时可能里面有很多重复的条,比如: +-----------+---------+| coupon_id | user_id |+-----------+---------+| 8 | 1 ...

  6. bzoj3991 [SDOI2015]寻宝游戏 树链的并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3991 题解 貌似这个东西叫做树链的并,以前貌似写过一个类似的用来动态维护虚树. 大概就是最终的 ...

  7. bzoj3589 动态树 树链剖分+容斥

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3589 题解 事件 \(0\) 不需要说,直接做就可以了. 事件 \(1\) 的话,考虑如果直接 ...

  8. 专家告诉你!如何避免黑客BGP劫持?

    BGP前缀劫持是针对Internet组织的持久威胁,原因是域间路由系统缺乏授权和身份验证机制. 仅在2017年,数千起路由事件导致代价高昂的中断和信息拦截,而问题的确切程度未知.尽管在过去20年中已经 ...

  9. Dubbo学习-4-dubbo简单案例-1

    模拟一个需求,通过dubbo实现RPC调用: 这里用户服务模块的查询用户地址的功能,就是一个服务提供者,而订单服务模块的创建订单模块就是一个服务消费者: 1. 创建服务提供者的maven工程:user ...

  10. C语言 为什么要引入指针?

    https://blog.csdn.net/chengxuyuan997/article/details/81231679 正文 在说为什么引入指针这个问题前先带大家了解一下什么是指针? 指针最为简短 ...