Spring Security - 忽略请求参数规则的Url

Iva*_*vov 9 java spring spring-security

我有一个使用spring安全性的Web应用程序.它使用<intercept-url ../>元素来描述不同URL的访问过滤器.默认情况下,这不会考虑url的请求参数.我需要根据请求参数设置url的自定义安全规则.所以我做了以下事情:

1)我创建了一个bean后处理器类,它将为spring安全机制启用请求参数选项:

<beans:beans>
    . . .
    <beans:bean class="MySecurityBeanPostProcessor">
        <beans:property name="stripQueryStringFromUrls" value="false" />
    </beans:bean>
    . . .
</beans:beans>
Run Code Online (Sandbox Code Playgroud)

和代码:

public class MySecurityBeanPostProcessor implements BeanPostProcessor {

    private Boolean stripQueryStringFromUrls = null;

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof DefaultFilterInvocationSecurityMetadataSource && stripQueryStringFromUrls != null) {
            ((DefaultFilterInvocationSecurityMetadataSource) bean)
                .setStripQueryStringFromUrls(stripQueryStringFromUrls.booleanValue());
        }
        return bean;
    }

    // code stripped for clarity
}
Run Code Online (Sandbox Code Playgroud)

这应该设置spring安全元数据源以考虑请求参数.我调试了上面的代码,stripQueryStringFromUrls正在设置属性.

2)在我的安全上下文xml中,我有以下定义:

<intercept-url pattern="/myUrl?param=value" access="!isAuthenticated() or hasRole('ROLE_GUEST')" />
<intercept-url pattern="/myUrl" filters="none" />
...
<intercept-url pattern="/**" access="isAuthenticated()" />
Run Code Online (Sandbox Code Playgroud)

如您所见,我需要仅在用户未经过身份验证或使用来宾帐户时才使用指定的参数访问URL.另外,我为同一个网址添加了规则,但没有任何没有过滤器的参数.

据我所知,春季安全应配置提供更具体的网址之前不太确切的,因为否则链将首先检测更一般的规则,不会继续更具体的了.这就是为什么我希望带有params的url更具体,因此被拒绝访问经过身份验证的非来宾用户.相反,下面定义的更一般的规则适用.这是输出:

INFO [STDOUT] 186879 [http-0.0.0.0-8080-1] DEBUG org.springframework.security.web.FilterChainProxy - 候选人是:'/ myUrl'; pattern是/ myUrl; 匹配=真

INFO [STDOUT] 186879 [http-0.0.0.0-8080-1] DEBUG org.springframework.security.web.FilterChainProxy - /myUrl?param = value有一个空的过滤列表

我还试图删除url的规则,没有params.然后,过滤器选择/**模式并要求用户登录,而不是使用params工作的url规则.输出是:

INFO [STDOUT] 73066 [http-0.0.0.0-8080-1] DEBUG org.springframework.security.web.FilterChainProxy - 候选人是:'/ myUrl'; 模式是/**; 匹配=真

INFO [STDOUT] 73068 [http-0.0.0.0-8080-1] DEBUG org.springframework.security.web.FilterChainProxy - /myUrl?param =附加过滤器链中第1位的值为8; 触发过滤器:'SecurityContextPersistenceFilter'

该应用程序使用Java 1.6编写,使用Spring v3.0,并在Linux机器上部署在JBoss v5.1.0-GA上.我没有线索为什么过滤器按照我描述的方式运行.非常感谢您的帮助和建议.


编辑:

作为结论,我观察到的/myUrl?param=value是永远不会应用过滤器 - 就好像忽略了security-context.xml中的条目一样.这符合我迄今为止观察到的行为.我也曾尝试更换filters="none"access="permitAll",切换到正则表达式(并相应地改变模式-例如/myUrl?param=value\A/myUrl\?param=value\Z),并在所有的变化我得到的行为是相同的.


编辑2:

这里描述的问题实际上是无效的.原因如下:出现问题的项目由于内部库冲突和不兼容而排除了一些弹簧包,而整个设置在某种程度上起作用.我从来没有意识到这一点,实际上这种不合适的配置使整个问题过时了.具体原因是isAuthenticated()和isAnonymous()方法的实现没有按预期工作,因此这里提供的任何建议都不起作用.

Sha*_*eep 9

在Spring Security 3.0中,这是(可以理解)常见的混淆源,因为使用filters="none"添加带有空过滤器列表的模式,FilterChainProxy而使用access属性会将安全访问规则添加到FilterSecurityInterceptor用于保护URL 的安全访问规则中.

匹配过程是:

  1. FilterChainProxy 将请求与过滤器链匹配
  2. 如果过滤器链非空,则将检查请求 FilterSecurityInterceptor

这两个类都维护一个单独的有序匹配列表,它们按照您定义它们的顺序应用,但是您需要了解下面实际上有两个单独的bean正在配置而没有直接连接.

在一个简单的命名空间应用程序中,该<http>块正在向FilterChainProxywith模式添加单个过滤器链/**.filters="none"您添加的任何模式都会在实际链之前放置空过滤器链.

Spring Security 3.1中的情况有了很大改进,因为您通过使用单独的<http>块来配置单独的过滤器链,该块更直观地映射到Bean级别实际发生的事件.该请求匹配过程也已经改善了很多,现在使用一个RequestMatcher接口的一切.配置<http>块时,也可以使用此模式而不是模式.

所以,你最好的选择可能是升级.然后,您可以实现一个RequestMatcher检查您要查找的参数是否存在MyParamRequestMatcher,然后使用:

<http request-matcher-ref="myParamMatcher" security="none" />

<bean:bean id="myParamMatcher" class="MyParamRequestMatcher" />

<http>
    <!-- Define the default filter chain configuration here -->
</http>
Run Code Online (Sandbox Code Playgroud)

请注意,使用URL模式匹配参数通常不是很安全,因为通过重新排序URL,添加虚假模式等很容易绕过.您的情况可能没问题,因为带参数的版本允许不安全的访问,并且您的模式需要对其他情况进行身份验证.

如果你想继续使用3.0,你最好的选择是避免使用filters="none"(isAnonymous()改为使用)并且可能使用正则表达式匹配而不是ant路径,以便你可以更容易地匹配查询字符串.再次,我应该重复规则这个规则方式几乎可以肯定被绕过,所以不要依赖它们来提高安全性,并确保默认情况下你是安全的.


更新:

作为我对使用正则表达式匹配的建议的测试permitAll,如果我在Spring Security的3.0.x分支中修改"教程"示例应用程序,如下所示:

<http use-expressions="true" path-type="regex">
    <intercept-url pattern="\A/secure/extreme/.*\Z" access="hasRole('ROLE_SUPERVISOR')"/>
    <intercept-url pattern="\A/secure/index.jsp\?param=value\Z" access="permitAll" />
    <intercept-url pattern="\A/secure/.*\Z" access="isAuthenticated()" />
    <intercept-url pattern="/.*" access="permitAll" />
    ...
</http>
Run Code Online (Sandbox Code Playgroud)

然后我确实得到了预期的行为:

[DEBUG,FilterChainProxy] Candidate is: '/secure/index.jsp?param=value'; pattern is /.*; matched=true
[DEBUG,FilterChainProxy] /secure/index.jsp?param=value at position 1 of 12 in additional filter chain; firing Filter: 'ConcurrentSessionFilter'
...
[DEBUG,FilterChainProxy] /secure/index.jsp?param=value at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
[DEBUG,FilterChainProxy] /secure/index.jsp?param=value at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
[DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource] Candidate is: '/secure/index.jsp?param=value'; pattern is \A/secure/extreme/.*\Z; matched=false
[DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource] Candidate is: '/secure/index.jsp?param=value'; pattern is \A/secure/index.jsp\?param=value\Z; matched=true
[DEBUG,FilterSecurityInterceptor] Secure object: FilterInvocation: URL: /secure/index.jsp?param=value; Attributes: [permitAll]
Run Code Online (Sandbox Code Playgroud)

它显示FilterChainProxy匹配,.*然后FilterSecurityInterceptor匹配确切的URL和参数.