Spring Security学习笔记之ChannelProcessingFilter

来源:互联网 发布:荒野行动知乎 编辑:程序博客网 时间:2024/06/06 08:46
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 0
原创粉丝点击