0

我正在尝试使用<authorize>标签的spring security的“url”属性。我遇到了一个奇怪的情况,标签似乎没有生效。

我的业务需要是使用两个<http>元素,一个用于 Web 服务访问,另一个用于普通用户访问:Web 服务访问是无状态的,但用户访问是基于会话的,这就是我们需要两个 http 元素的原因。

为了说明这个问题,我将使用 spring security 3.1.4 教程来代替。<http>我可以通过只在 spring 配置文件中添加一个额外的元素来重现这个问题。

教程中的原始 applicationContext-securiy.xml 定义如下:

<http pattern="/static/**" security="none"/>
<http pattern="/loggedout.jsp" security="none"/>

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

它的登录页面 index.jsp 使用“授权”标签,如下所示:

<sec:authorize url='/secure/index.jsp'>
<p>
    You can currently access "/secure" URLs.
</p>
</sec:authorize>

当用户第一次尝试访问此页面时,标签将检查对 url '/secure/index.jsp' 的权限,这需要身份验证,因此标签不会取代其内容和 UI 显示消息。

您的主要对象是....:null

现在,通过在最后一个“http”元素之前添加一个新的 http 元素来更改 applicationContext-security.xml

<http pattern="/static/**" security="none"/>
<http pattern="/loggedout.jsp" security="none"/>

<!--This is the new element added-->
<http pattern="/user/**"
     use-expressions="true">
    <intercept-url pattern="/user/**" access="hasRole('user')"/>
    <http-basic />
 </http>

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

现在,我访问 index.jsp(还没有登录),页面实际上打印出一条消息:

您的主要对象是....: null 您当前可以访问“/secure” URL。您当前可以访问“/secure/extreme” URL。

在这种情况下,“授权”标签的计算结果为真,即使我还没有登录!

我尝试通过源代码DefaultFilterInvocationSecurityMetadataSource进行调试,发现当第一个http请求“/index.jsp”进来时,它使用applicationContext-security.xml中的默认元素(最后一个)但是当“”标签尝试检查对“/secure/index.jsp”的访问,DefaultFilterInvocationSecurityMetadataSource 正在使用新元素,它的 getAttributes() 返回 null 到 DefaultWebInvocationPrivilegeEvaluator,最终返回 true。

这对我来说看起来像是一个弹簧安全错误:授权标签 url,“/secure/index.jsp”应该匹配默认的“http”,而不是另一个。

我使用的一种解决方法是将“/secure/index.jsp”和“/secure/extreme/index.jsp”的“intercept-url”定义从默认的“http”复制到新的“http”元素,然后UI 按预期工作。但我不想复制代码!

任何想法都值得赞赏。

4

2 回答 2

1

我已经解决了这个问题,如下所示。

爪哇:

package com.github.kazuki43zoo.web.security;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
import org.springframework.stereotype.Component;

@Component
public class CustomWebInvocationPrivilegeEvaluatorProvideFilter implements Filter,
        WebInvocationPrivilegeEvaluator, BeanPostProcessor {

    private List<WebInvocationPrivilegeEvaluator> webInvocationPrivilegeEvaluators = new ArrayList<>();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        request.setAttribute(WebAttributes.WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE, this);
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        webInvocationPrivilegeEvaluators.clear();
    }

    @Override
    public boolean isAllowed(String uri, Authentication authentication) {
        for (WebInvocationPrivilegeEvaluator privilegeEvaluator : webInvocationPrivilegeEvaluators) {
            if (!privilegeEvaluator.isAllowed(uri, authentication)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean isAllowed(String contextPath, String uri, String method,
            Authentication authentication) {
        for (WebInvocationPrivilegeEvaluator privilegeEvaluator : webInvocationPrivilegeEvaluators) {
            if (!privilegeEvaluator.isAllowed(contextPath, uri, method, authentication)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        if (bean instanceof WebInvocationPrivilegeEvaluator
                && !bean.getClass().isAssignableFrom(getClass())) {
            webInvocationPrivilegeEvaluators.add((WebInvocationPrivilegeEvaluator) bean);
        }
        return bean;
    }

}

网页.xml:

<filter>
    <filter-name>CustomWebInvocationPrivilegeEvaluatorProvideFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetBeanName</param-name>
        <param-value>customWebInvocationPrivilegeEvaluatorProvideFilter</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CustomWebInvocationPrivilegeEvaluatorProvideFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
于 2014-07-13T05:35:45.590 回答
0

这对我有用:

org.springframework.context.ApplicationContext ctx = org.springframework.web.context.support.WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
java.util.Map<String, org.springframework.security.web.access.WebInvocationPrivilegeEvaluator>
        wipes = ctx.getBeansOfType(org.springframework.security.web.access.WebInvocationPrivilegeEvaluator.class);

if(wipes.size() > 0){
    //I need last one
    org.springframework.security.web.access.WebInvocationPrivilegeEvaluator appEvaluator =
            (WebInvocationPrivilegeEvaluator)wipes.values().toArray()[wipes.size() - 1];

    //set request attribute so that JSP tag can use it        request.setAttribute(org.springframework.security.web.WebAttributes.WEB_INVOCATION_PRIVILEGE_EVALUATOR_ATTRIBUTE
            , appEvaluator);

}
于 2013-09-17T13:19:57.020 回答