【问题标题】:Custom Access Rules for Spring SecuritySpring Security 的自定义访问规则
【发布时间】:2013-08-23 14:56:17
【问题描述】:

通常您会定义一些拦截 URL 模式来配置对具有弹簧安全性的页面的访问

<http use-expressions="true">
    <intercept-url pattern="/**/secure/**" access="hasRole('ROLE_SECURE_USER')" />
    ...
</http>

我们现在有一些事先不知道 url 的页面。但是我们可以编写一段代码来决定是否应该保护特定页面,即如果必须保护页面,我们可以提供返回 true 的服务。所以我们想做的是这样的:

<http use-expressions="true">
    <intercept decide="@service.mustProtect()" access="hasRole('ROLE_SECURE_USER')" />
    ...
</http>

如何使用 Spring 实现这一点?我们是否必须编写自定义过滤器?您将如何实现这样的过滤器?

【问题讨论】:

    标签: spring security spring-security


    【解决方案1】:

    实际上,通过在FilterSecurityInterceptor 之前注入自定义过滤器来解决我们的问题很容易。然后您可以在过滤器的doFilter 方法中抛出AccessDeniedException 来触发身份验证。

    Spring 安全配置:

    <http use-expressions="true">
        <custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="accessFilter"/>
        ...
    </http>
    
    <beans:bean id="accessFilter" class="xyz.AccessFilter" />
    

    过滤器:

    public class AccessFilter extends GenericFilterBean {
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            if (!currentUserCanAccessPage(request)) {
                throw new AccessDeniedException();
            }
            chain.doFilter(request,response)
        }
    
        private boolean currentUserCanAccessPage(ServletRequest request) {
            //implement
        }
    }
    

    【讨论】:

      【解决方案2】:

      &lt;intercept-url&gt; 标签所做的只是填充一个存储库(称为SecurityMetadataSource),其中RequestMatchers 映射到ConfigAttributes。 RequestMatchers 是基于pattern 属性生成的,而ConfigAttributes 只是保存access 属性中指定的字符串。

      当传入请求命中FilterSecurityInterceptor 过滤器时,它将遍历这些映射的列表以找到第一个条目,其中RequestMatcher 表示匹配,以确定它必须满足什么样的访问限制强制(由映射的ConfigAttribute 描述)。

      现在,如果你能把你自己的RequestMatcher 实现放到这张地图上,你的要求就基本解决了。困难在于命名空间配置不适合这种用例,它只能将pattern 属性解释为AntPathRequestMatcherRegexRequestMatcher

      这意味着您必须在 bean 级别配置安全基础架构,因为 &lt;http&gt; 元素会创建自己的无法替换的 FilterSecurityInterceptor

      this article你可以找到关于如何编写这种手动安全配置的很大帮助。

      【讨论】:

      • 如果不允许当前用户访问该页面,是否可以在FilterSecurityInterceptor 前面添加一个自定义过滤器,该过滤器会抛出AccessDeniedException
      • 当然,好点,ExceptionTranslationFilter 不关心AccessDeniedException 被抛出的位置。它不必来自定制的FilterSecurityInterceptor。您也可以提供自己的过滤器,设置起来可能会容易得多。
      猜你喜欢
      • 2019-11-15
      • 1970-01-01
      • 2019-05-02
      • 1970-01-01
      • 2017-01-20
      • 2017-05-25
      • 1970-01-01
      • 2012-11-19
      • 2012-12-07
      相关资源
      最近更新 更多