如何动态决定<intercept-url>访问 Spring Security 中的属性值? [英] How to dynamically decide <intercept-url> access attribute value in Spring Security?

查看:24
本文介绍了如何动态决定<intercept-url>访问 Spring Security 中的属性值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Spring Security中,我们使用intercept-url标签来定义对URL的访问,如下所示:

In Spring Security we use the intercept-url tag to define the access for URLs as below:

<intercept-url pattern="/**" access="ROLE_ADMIN" />
<intercept-url pattern="/student" access="ROLE_STUDENT" />

这是在 applicationContext-security.xml 中硬编码的.我想从数据库表中读取访问值.我已经定义了我自己的 UserDetailsS​​ervice 并且我从数据库中读取了登录用户的角色.如何在运行时将这些角色分配给 URL 模式?

This is hard coded in applicationContext-security.xml. I want to read the access values from a database table instead. I have defined my own UserDetailsService and I read the roles for the logged in user from the database. How do I assign these roles to the URL patterns during runtime?

推荐答案

Spring-security 中的 FilterInvocationSecurityMetadataSourceParser 类(使用源代码在 STS 中尝试 Ctrl/Cmd+Shift+T)解析拦截 url 标签并创建实例ExpressionBasedFilterInvocationSecurityMetadataSource,它扩展了 DefaultFilterInvocationSecurityMetadataSource,后者实现了 FilterInvocationSecurityMetadataSource,后者扩展了 SecurityMetadataSource.

The FilterInvocationSecurityMetadataSourceParser class in Spring-security (try Ctrl/Cmd+Shift+T in STS with the source code) parses the intercept-url tags and creates instances of ExpressionBasedFilterInvocationSecurityMetadataSource, that extends DefaultFilterInvocationSecurityMetadataSource that implements FilterInvocationSecurityMetadataSource that extends SecurityMetadataSource.

我所做的是创建一个实现 FilterInvocationSecurityMetadataSource 的自定义类,OptionsFromDataBaseFilterInvocationSecurityMetadataSource.我使用 DefaultFilterInvocationSecurityMetadataSource 作为基础来使用 urlMatcher,实现 support() 方法等.

What I did is to create a custom class that implements FilterInvocationSecurityMetadataSource, OptionsFromDataBaseFilterInvocationSecurityMetadataSource. I used DefaultFilterInvocationSecurityMetadataSource as base to use urlMatcher, to implement the support() method and something like that.

那么你必须实现这些方法:

Then you must to implement these methods:

  • Collection getAttributes(Object object),您可以在其中访问数据库,搜索受保护的对象"(通常是要访问的 URL)以获得允许的 ConfigAttribute(通常是 ROLE)

  • Collection getAttributes(Object object), where you can access to database, searching for the 'object' being secured (normally the URL to access) to obtain the allowed ConfigAttribute's (normally the ROLE's)

布尔支持(类 clazz)

boolean supports(Class clazz)

集合 getAllConfigAttributes()

Collection getAllConfigAttributes()

注意后者,因为它在启动时被调用,并且此时可能没有很好地配置(我的意思是,自动装配数据源或持久性上下文,取决于您使用的是什么).web环境下的解决方案是在web.xml中配置contextConfigLocation,在applicationContext-security.xml之前加载applicationContext.xml

Be careful with the later, because it's called at startup and maybe is not well configured at this time (I mean, with the datasources or persistence context autowired, depending on what are you using). The solution in a web environment is to configure the contextConfigLocation in the web.xml to load the applicationContext.xml before the applicationContext-security.xml

最后一步是自定义 applicationContext-security.xml 以加载此 bean.

The final step is to customize the applicationContext-security.xml to load this bean.

为此,我在此文件中使用了常规 bean 而不是安全命名空间:

For doing that, I used regular beans in this file instead of the security namespace:

    <beans:bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
    <filter-chain-map path-type="ant">
        <filter-chain pattern="/images/*" filters="none" />
        <filter-chain pattern="/resources/**" filters="none" />
        <filter-chain pattern="/**" filters="
        securityContextPersistenceFilter,
        logoutFilter,
        basicAuthenticationFilter,
        exceptionTranslationFilter,
        filterSecurityInterceptor" 
    />
    </filter-chain-map>
</beans:bean>

您必须定义所有相关的 bean.例如:

You have to define all the related beans. For instance:

    <beans:bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
    <beans:property name="authenticationManager" ref="authenticationManager"></beans:property>
    <beans:property name="accessDecisionManager" ref="affirmativeBased"></beans:property>
    <beans:property name="securityMetadataSource" ref="optionsFromDataBaseFilterInvocationSecurityMetadataSource"></beans:property>
    <beans:property name="validateConfigAttributes" value="true"/></beans:bean>

我知道这不是一个很好解释的答案,但它并不像看起来那么难.

I know that is not a well explained answer, but it's not as difficult as it seems.

只要以spring source为基础,你就会得到你想要的.

Just use the spring source as base and you will obtain what you want.

使用数据库中的数据进行调试,会对您有很大帮助.

Debugging with the data in your database, will help you a lot.

这篇关于如何动态决定&lt;intercept-url&gt;访问 Spring Security 中的属性值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆