你好,我想制作一个拦截 url 模式并通过在 spring security 中使用 sql 查询动态访问。
通常我们在 XML 中使用这种类型的表示法,我想从数据库中获取这些值(/add-role 和 ROLE_ADMIN)。
<intercept-url pattern="/add-role*" access="ROLE_ADMIN" />
是否可以动态地执行此操作?
最佳答案
免责声明
作为Spring Security FAQ提到,你应该做的第一件事是问我真的应该这样做吗?安全性很复杂,配置应该经过广泛的测试。允许动态更改配置只会使事情变得更加复杂,使应用程序更容易受到攻击。如果您确实想这样做,常见问题解答概述了实现此目的的基本方法。我在下面扩展了常见问题解答的答案。
实现自定义 FilterInitationSecurityMetadataSource
要动态获取安全 URL 映射,您可以实现自己的 FilterInitationSecurityMetadataSource。下面给出了一个示例实现。
注意:请记住,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,您可能会遇到 SEC-1957该问题已在 Spring Security 3.1.1+ 中修复。请尝试更新到最新版本来解决此问题。
关于spring - 使用 SQL 查询的动态 Spring Security,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8381776/