【问题标题】:Spring security hasPermission is not workingSpring security hasPermission 不起作用
【发布时间】:2018-02-03 07:40:51
【问题描述】:

我正在尝试将 Spring Security 集成到我的 Spring Web 应用程序中。基本上我需要根据用户权限隐藏一些菜单。这就是我所做的。

我在类路径中的 JARS 下面添加了。

spring-security-acl-4.0.2.RELEASE.jar
spring-security-config-4.0.2.RELEASE.jar
spring-security-core-4.0.2.RELEASE.jar
spring-security-taglibs-4.0.1.RELEASE.jar
spring-security-web-4.0.2.RELEASE.jar

以下是 web.xml 中的条目

<context-param>
    <param-name>log4jConfiguration</param-name>
    <param-value>/WEB-INF/web_log4j.xml</param-value>
</context-param>

<listener>
    <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring-root.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

我写了一个类 CustomPermissionEvaluator,如下所示。

public class CustomPermissionEvaluator implements PermissionEvaluator{


@Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
    HttpServletRequest request = (HttpServletRequest) targetDomainObject;
    Profile userProfile = (Profile) request.getSession().getAttribute("testprofile");
    if (userProfile.getPermissionMap().get(String.valueOf(permission)) != null) {
        return true;
    } else {
        return false;
    }
}

@Override
public boolean hasPermission(Authentication arg0, Serializable arg1,
        String arg2, Object arg3) {
    // TODO Auto-generated method stub
    return false;
}

}

在此之后,我编写了 SecurityConfig 文件。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
public void configure(WebSecurity web) throws Exception {
    DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
    handler.setPermissionEvaluator(new CustomPermissionEvaluator());
    web.expressionHandler(handler);
}

}

我的 spring-root.xml 中有以下条目

<sec:global-method-security pre-post-annotations="enabled">
    <sec:expression-handler ref="expressionHandler" />
</sec:global-method-security>
<bean id="expressionHandler"
    class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
    <property name="permissionEvaluator" ref="permissionEvaluator" />
</bean>
<bean id="permissionEvaluator" class="main.java.com.config.CustomPermissionEvaluator" />

现在在我的 JSP 文件中,我在 taglib 下使用。

及以下代码

<sec:authorize access="hasPermission('cadastra_categoria', #request)">      
                <div id="TEST">
                </div>
            </sec:authorize>

但它不起作用。任何建议将不胜感激。

【问题讨论】:

  • 是否有指标、错误之类的?放置断点时,hasPermission 调用是否到达了实现?我认为您缺少安全过滤器链docs.spring.io/spring-security/site/docs/4.2.3.RELEASE/…,但这是一个假设
  • 不,我没有收到任何错误,也没有调用 CustomPermissionEvaluator 。
  • 你确定你正确引用你的bean吗? class="main.java.com.config.CustomPermissionEvaluator" - 这不应该没有main.java吗?
  • @aturkovic 是的,我指的是我的 bean 是正确的。项目就是这样。
  • 您是否尝试过添加一些日志来查看您的评估是否真的被调用?此外,一些日志记录用于调试并查看您是否遇到任何异常?

标签: java spring spring-mvc spring-security


【解决方案1】:

据我了解,您已经创建了 CustomPermissionEvaluator 类,但您没有检查您的 Authenticated 用户权限。

我是直接写代码CustomPermissionEvaluator为了清楚我的意思可能有任何错误:

public class CustomPermissionEvaluator implements PermissionEvaluator {

    public boolean hasPermission(Authentication auth, Object targetDomainObject, Object permission) {
        if ((auth == null) || (targetDomainObject == null) || !(permission instanceof String)){
            return false;
        }

        Profile userProfile = (Profile) request.getSession().getAttribute("testprofile");
        String targetType = userProfile.getPermissionMap().get(String.valueOf(permission));

        return hasPrivilege(auth, targetType, permission.toString().toUpperCase());
    }

    private boolean hasPrivilege(Authentication auth, String targetType, String permission) {
        for (GrantedAuthority grantedAuth : auth.getAuthorities()) {
            if (grantedAuth.getAuthority().startsWith(targetType)) {
                if (grantedAuth.getAuthority().contains(permission)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public boolean hasPermission(Authentication arg0, Serializable arg1, String arg2, Object arg3) {
        // TODO Auto-generated method stub
        return false;
    }
}

【讨论】:

    【解决方案2】:

    "hasPermission('cadastra_categoria', #request)"

    实际上,有效调用必须交换参数,第一个必须是目标域对象,第二个 - 权限:

    hasPermission(#request, 'cadastra_categoria')
    

    我假设您还仔细检查了是否已根据需要将 sec taglib 导入到您的 JSP 中

    <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
    

    最后,正如answer 的第二部分所阐明的那样,定义以下内容:

    import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
    
    public class AnnotationConfigDispatcherServletInitializer extends
        AbstractAnnotationConfigDispatcherServletInitializer {
    
      @Override
      protected Class<?>[] getRootConfigClasses() {
        return new Class[] {
          SecurityConfig.class //your SecurityConfig
        };
      }
    }
    

    确保在您的 Web 应用程序启动期间调用 configure(WebSecurity web)

    【讨论】:

    • 别说了,我昨天解决了我的问题,并将更新解决方案。感谢您的帮助。
    【解决方案3】:

    请尝试 hasAnyRole 并检查一次,即

    <sec:authorize access="hasAnyRole('ROLE_NAME')"> TEST </sec:authorize>
    

    【讨论】:

      猜你喜欢
      • 2012-01-02
      • 2017-10-30
      • 2015-09-11
      • 2013-06-25
      • 2017-06-08
      • 2018-06-26
      • 2015-08-27
      • 2013-04-28
      • 2016-02-16
      相关资源
      最近更新 更多