转至:Elim的博客http://elim.iteye.com/blog/2161648html
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.htmlweb
<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>
Spring security容许咱们在配置文件中配置多个http元素,以针对不一样形式的URL使用不一样的安全控制。Spring Security将会为每个http元素建立对应的FilterChain,同时按照它们的声明顺序加入到FilterChainProxy。因此当咱们同时定义多个http元素时要确保将更具备特性的URL配置在前。spring
<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。api
ChannelProcessingFilter,若是你访问的channel错了,那首先就会在channel之间进行跳转,如http变为https。安全
SecurityContextPersistenceFilter,这样的话在一开始进行request的时候就能够在SecurityContextHolder中创建一个SecurityContext,而后在请求结束的时候,任何对SecurityContext的改变均可以被copy到HttpSession。cookie
ConcurrentSessionFilter,由于它须要使用SecurityContextHolder的功能,并且更新对应session的最后更新时间,以及经过SessionRegistry获取当前的SessionInformation以检查当前的session是否已通过期,过时则会调用LogoutHandler。session
认证处理机制,如UsernamePasswordAuthenticationFilter,CasAuthenticationFilter,BasicAuthenticationFilter等,以致于SecurityContextHolder能够被更新为包含一个有效的Authentication请求。app
SecurityContextHolderAwareRequestFilter,它将会把HttpServletRequest封装成一个继承自HttpServletRequestWrapper的SecurityContextHolderAwareRequestWrapper,同时使用SecurityContext实现了HttpServletRequest中与安全相关的方法。jsp
JaasApiIntegrationFilter,若是SecurityContextHolder中拥有的Authentication是一个JaasAuthenticationToken,那么该Filter将使用包含在JaasAuthenticationToken中的Subject继续执行FilterChain。ui
RememberMeAuthenticationFilter,若是以前的认证处理机制没有更新SecurityContextHolder,而且用户请求包含了一个Remember-Me对应的cookie,那么一个对应的Authentication将会设给SecurityContextHolder。
AnonymousAuthenticationFilter,若是以前的认证机制都没有更新SecurityContextHolder拥有的Authentication,那么一个AnonymousAuthenticationToken将会设给SecurityContextHolder。
ExceptionTransactionFilter,用于处理在FilterChain范围内抛出的AccessDeniedException和AuthenticationException,并把它们转换为对应的Http错误码返回或者对应的页面。
FilterSecurityInterceptor,保护Web URI,而且在访问被拒绝时抛出异常。
使用NameSpace时添加Filter到FilterChain是经过http元素下的custom-filter元素来定义的。定义custom-filter时须要咱们经过ref属性指定其对应关联的是哪一个Filter,此外还须要经过position、before或者after指定该Filter放置的位置。eg:position=”CAS_FILTER”就表示将定义的Filter放在CAS_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 | 无 |
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与对应的权限关系。
经过前面的介绍咱们知道在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所捕获。