Spring Security学习笔记之ChannelProcessingFilter

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协议).
第二步, 判断当前请求是否与协议相符. 若不相符, 则修改协议并自动跳转. 若相符, 则跳到下一个过滤器.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值