Spring Security 的 hasPermission 方法无法正常工作

8

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

我在类路径中添加了以下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);
}

}

I have below entries in my 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>

但是它没有起作用。欢迎提出任何建议。


你确定你正确地引用了你的bean吗?class="com.config.CustomPermissionEvaluator" - 这里不应该有 main.java 吗? - alturkovic
@N4zroth,CustomPermissionEvaluator已被Spring加载。我通过放置记录器来确认这一点。但是,当我使用Spring安全标签从JSP调用它时,它并没有被调用。 - GD_Java
你能检查一下这个链接吗?https://dev59.com/YIDba4cB1Zd3GeqPBTdx - Amit K Bist
@AmitKBist 我已经检查过了,对我没有用。 - GD_Java
请查看以下链接以了解有关“为什么我的自定义PermissionEvaluator不起作用”的问题:https://dev59.com/0n3aa4cB1Zd3GeqPe5L_ - Amit K Bist
显示剩余5条评论
3个回答

2

"hasPermission(#request, 'cadastra_categoria')"

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

hasPermission(#request, 'cadastra_categoria')

我假设您已经仔细检查,确保按要求在JSP中导入了sec标签库。
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

最后,正如在答案的第二部分中澄清的那样,定义以下内容:

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)


算了吧,我昨天解决了我的问题,并将更新解决方案。感谢你们的帮助。 - GD_Java

2
根据我的理解,您创建了CustomPermissionEvaluator类,但没有检查您认证的用户权限。
我直接编写代码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;
    }
}

0
请尝试使用hasAnyRole并检查一次,即:
<sec:authorize access="hasAnyRole('ROLE_NAME')"> TEST </sec:authorize>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接