您好我想制作一个拦截url模式并通过在spring security中使用SQL查询动态访问.
通常我们在XML中使用这种表示法,我想从数据库中获取这些值(/ add-role和ROLE_ADMIN).
<intercept-url pattern="/add-role*" access="ROLE_ADMIN" />
有可能动态地这样做吗?
解决方法
放弃
正如Spring Security FAQ所提到的,你应该做的第一件事是问我应该真的这样做吗?安全性很复杂,应该对配置进行广泛测试.允许配置动态更改只会使使应用程序更容易受到攻击的事情变得更加复杂.如果你真的想这样做,FAQ概述了实现这一目标的基本方法.我已经扩展了以下常见问题解答的答案.
实现自定义FilterInvocationSecurityMetadataSource
要动态获取安全URL映射,您可以实现自己的FilterInvocationSecurityMetadataSource.下面给出一个示例实现.
注意:请记住,将为Spring Security拦截的每个请求调用getAttributes,因此您很可能需要某种缓存.
public class JdbcFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource { public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { FilterInvocation fi = (FilterInvocation) object; String url = fi.getRequestUrl(); HttpServletRequest request = fi.getHttpRequest(); // Instead of hard coding the roles lookup the roles from the database using the url and/or HttpServletRequest // Do not forget to add caching of the lookup String[] roles = new String[] { "ROLE_ADMIN","ROLE_USER" }; return SecurityConfig.createList(roles); } public Collection<ConfigAttribute> getAllConfigAttributes() { return null; } public boolean supports(Class<?> clazz) { return FilterInvocation.class.isAssignableFrom(clazz); } }
创建一个BeanPostProcessor
你不能使用命名空间来连接它,所以拿另一个tip from the FAQ你可以使用一个看起来像这样的BeanPostProcessor:
public class FilterInvocationSecurityMetadataSourcePostProcessor implements BeanPostProcessor,InitializingBean { private FilterInvocationSecurityMetadataSource securityMetadataSource; public Object postProcessAfterInitialization(Object bean,String name) { if (bean instanceof FilterSecurityInterceptor) { ((FilterSecurityInterceptor)bean).setSecurityMetadataSource(securityMetadataSource); } return bean; } public Object postProcessBeforeInitialization(Object bean,String name) { return bean; } public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) { this.securityMetadataSource = securityMetadataSource; } public void afterPropertiesSet() throws Exception { Assert.notNull(securityMetadataSource,"securityMetadataSource cannot be null"); } }
XML配置
然后,假设上述两个bean都在包示例中,您将添加以下配置
<bean class="sample.FilterInvocationSecurityMetadataSourcePostProcessor"> <property name="securityMetadataSource"> <bean class="sample.JdbcFilterInvocationSecurityMetadataSource"/> </property> </bean>
可能的问题
如果最终得到ClassCastException,则可能会遇到在Spring Security 3.1.1中修复的SEC-1957.请尝试更新到最新版本以解决此问题.