spring - 使用 SQL 查询的动态 Spring Security

标签 spring spring-mvc spring-security

你好,我想制作一个拦截 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/

相关文章:

java - 如何在响应正文中返回 ConstraintViolationException 消息?

java - 如何在Freemarker模板中访问Spring MVC模型对象?

java - SpringBoot Controller 无法解析名称为 'home' 的 View

java - 如何删除(多线程)事务性 Spring/JPA 中的实体

multithreading - Spring @Async 和 AbstractRoutingDataSource

java - spring-data 多数据源配置运行但插入错误的数据源

java - 使用 Spring 3 RequestMapping Annotation 匹配 "Rest of the URL"

grails - Grails Spring安全认证-未显示GSP错误

java - SpringMVC(安全)- 403 错误

java - 在 Weblogic 12c 上部署 Spring Security SAML 扩展时出现问题