Spring Security-具有请求参数规则的网址被忽略
我有一个使用Spring Security的Web应用程序。它使用<intercept-url ../>
元素描述不同URL的访问过滤器。默认情况下,这不考虑url的请求参数。我需要根据请求参数设置URL的自定义安全规则。所以我做了以下工作:
1)我创建了一个bean后处理器类,它将为spring安全机制启用request parameters选项:
<beans:beans> . . .
<beans:bean class="MySecurityBeanPostProcessor">
<beans:property name="stripQueryStringFromUrls" value="false" />
</beans:bean>
. . .
</beans:beans>
And the code:
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
}
这应该设置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()" />
如你所见,仅当用户未通过身份验证或使用来宾帐户时,我才需要使用指定的参数访问URL。另外,我为相同的url添加了一个规则,但没有任何参数,没有过滤器。
据我所知,应该配置Spring安全性在提供较低特定性之前提供较高特定性的url ,因为否则,链将首先检测到较通用的规则,而不会继续遵循较高特定性的规则。这就是为什么我希望带有params的url更具体,因此将拒绝对经过身份验证的非guest用户的访问。相反,下面定义的更通用的规则适用。这是输出:
INFO [STDOUT] 186879 [http-0.0.0.0-8080-1] DEBUG org.springframework.security.web.FilterChainProxy - Candidate is: ‘/myUrl’; pattern is /myUrl; matched=true
INFO [STDOUT] 186879 [http-0.0.0.0-8080-1] DEBUG org.springframework.security.web.FilterChainProxy - /myUrl?param=value has an empty filter list
我还尝试删除没有参数的url规则。然后,过滤器选择/**
模式并要求用户登录,而不是让我的参数带有参数的url起作用。的输出是:
INFO [STDOUT] 73066 [http-0.0.0.0-8080-1] DEBUG org.springframework.security.web.FilterChainProxy - Candidate is: ‘/myUrl’; pattern is
/**
; matched=trueINFO [STDOUT] 73068 [http-0.0.0.0-8080-1] DEBUG org.springframework.security.web.FilterChainProxy - /myUrl?param=value at position 1 of 8 in additional filter chain; firing Filter: ‘SecurityContextPersistenceFilter’
编辑:
得出的结论是,我观察到的/myUrl?param=value是从未应用过该过滤器-好像security-context.xml
中的条目被忽略了。这符合我到目前为止观察到的行为。我还尝试了将替换filters="none"为access="permitAll"
,切换为正则表达式(并相应地更改了模式-例如/myUrl?param=value变为\A/myUrl\?param=value\Z)
,并且在所有变体中,我得到的行为都是相同的。
编辑2:
这里描述的问题实际上是无效的。原因如下:存在问题的项目由于内部库冲突和不兼容而排除了一些spring软件包,而整个设置却以某种方式起作用。我从来没有意识到这一点,实际上,这种不纯净的配置使整个问题变得过时了。具体的原因是isAuthenticated()和isAnonymous()方法的实现未按预期工作,因此此处提供的任何建议均无效。
回答:
在Spring Security 3.0中,这是(可以理解的)一个常见的混乱根源,因为使用filters="none"
会将带有空过滤器列表的模式添加到,FilterChainProxy
而使用access属性则会将安全访问规则添加到FilterSecurityInterceptor
,用于保护URL 。
匹配过程为:
FilterChainProxy
将请求匹配到过滤器链- 如果过滤器链为非空,则请求将由
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>
请注意,使用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>
然后,我得到了预期的行为:
[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]
会显示FilterChainProxy
下方的匹配项,.*
然后是FilterSecurityInterceptor
与参数匹配的确切URL。
以上是 Spring Security-具有请求参数规则的网址被忽略 的全部内容, 来源链接: utcz.com/qa/428010.html