ChannelProcessingFilter通常是用来过滤哪些请求必须用https协议, 哪些请求必须用http协议, 哪些请求随便用哪个协议都行.
下面是自动配置SpringSecurity过滤器时的配置方式:
<sec:http entry-point-ref="myAuthenticationEntryPoint" > <sec:intercept-url pattern="/my_login" requires-channel="https"/> <sec:intercept-url pattern="/**" access="ROLE_USER"/> <!-- 映射安全端口. 用于当用户通过非安全端口访问时, 应用会自动跳转用安全端口访问 --> <sec:port-mappings> <sec:port-mapping http="8020" https="8021"/> </sec:port-mappings> ... </sec:http>
下面是手动配置SpringSecurity过滤器时的配置方式:
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy"> <constructor-arg> <list> <sec:filter-chain pattern="/login" filters="none"/> <sec:filter-chain pattern="/register" filters="none"/> <sec:filter-chain pattern="/accessDenied" filters="none"/> <sec:filter-chain pattern="/**/*.js" filters="none"/> <sec:filter-chain pattern="/**" filters="channelProcessingFilter, ..."/> </list> </constructor-arg> </bean> <bean id="channelProcessingFilter" class="org.springframework.security.web.access.channel.ChannelProcessingFilter"> <property name="channelDecisionManager" ref="channelDecisionManager"/> <property name="securityMetadataSource"> <sec:filter-security-metadata-source request-matcher="ant"> <!-- "/my_login"必须用https协议来发送 --> <sec:intercept-url pattern="/my_login" access="REQUIRES_SECURE_CHANNEL"/> <!-- 其他的可以用http或https协议来发送 --> <sec:intercept-url pattern="/**" access="ANY_CHANNEL"/> </sec:filter-security-metadata-source> </property> </bean> <bean id="channelDecisionManager" class="org.springframework.security.web.access.channel.ChannelDecisionManagerImpl"> <property name="channelProcessors"> <list> <ref local="secureChannelProcessor"/> <ref local="insecureChannelProcessor"/> </list> </property> </bean> <bean id="secureChannelProcessor" class="org.springframework.security.web.access.channel.SecureChannelProcessor"> <property name="entryPoint" ref="httpsEntryPort"/> </bean> <bean id="insecureChannelProcessor" class="org.springframework.security.web.access.channel.InsecureChannelProcessor"> <property name="entryPoint" ref="httpEntryPort"/> </bean> <bean id="httpEntryPort" class="org.springframework.security.web.access.channel.RetryWithHttpEntryPoint"> <property name="portMapper" ref="securePortMapper"/> </bean> <bean id="httpsEntryPort" class="org.springframework.security.web.access.channel.RetryWithHttpsEntryPoint"> <property name="portMapper" ref="securePortMapper"/> </bean> <!-- 这里做http与https端口的映射配置. 如果不配置, 默认的端口映射是"80-443"和"8080-8443" --> <bean id="securePortMapper" class="org.springframework.security.web.PortMapperImpl"> <property name="portMappings"> <map> <entry key="8020" value="8021"/> </map> </property> </bean>
下面看看ChannelProcessingFilter的doFilter()方法:
public class ChannelProcessingFilter extends GenericFilterBean { private ChannelDecisionManager channelDecisionManager; private FilterInvocationSecurityMetadataSource securityMetadataSource; public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; FilterInvocation fi = new FilterInvocation(request, response, chain); // 找出当前请求所需要的权限(attr的值可以是: ANY_CHANNEL, REQUIRES_SECURE_CHANNEL, REQUIRES_INSECURE_CHANNEL) Collection<ConfigAttribute> attr = this.securityMetadataSource.getAttributes(fi); if (attr != null) { if (logger.isDebugEnabled()) { logger.debug("Request: " + fi.toString() + "; ConfigAttributes: " + attr); } // 判断当前请求与协议是否相符 channelDecisionManager.decide(fi, attr); if (fi.getResponse().isCommitted()) { return; } } chain.doFilter(request, response); } ... }ChannelProcessingFilter主要有两个属性:channelDecisionManager: 判断当前请求与协议是否相符;securityMetadataSource: 储存请求与协议的对应关系.doFilter()方法主要做了两步:第一步, 找出当前请求所需要的协议. attr的值可以是ANY_CHANNEL(http和https都可以), REQUIRES_SECURE_CHANNEL(必须是https协议), REQUIRES_INSECURE_CHANNEL(必须是http协议).第二步, 判断当前请求是否与协议相符. 若不相符, 则修改协议并自动跳转. 若相符, 则跳到下一个过滤器.
本文介绍如何使用Spring Security配置HTTPS和HTTP请求,包括自动配置和手动配置两种方式,并详细解析了ChannelProcessingFilter的工作原理。
366

被折叠的 条评论
为什么被折叠?



