Spring + Spring Security + hasPermission不工作

时间:2011-11-21 07:26:25

标签: spring spring-security

我正在尝试使用Spring Security 3和Struts 2以及Spring DI。我在我的代码中放了hasRole()注释,它工作正常,但hasPermission()注释不起作用。我已经创建了表达式处理程序,自定义权限评估程序等。

这是代码

的applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans> 
 <import resource="mySecurity.xml"/>
<bean id="myAction" name="myAction" class="code.action.MyAction" autowire="byName">
</bean>
<bean id="permission" name="permission" class="code.permission.Permission" autowire="byName">
</bean>
<bean id="myEntity" name="myEntity" class="code.entities.MyEntity" autowire="byName">
</bean>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" 
    name="expressionHandler" autowire="byName">
</bean>
<bean class="code.permission.MyCustomPermissionEvaluator" id="customPermissionEvaluator" name="customPermissionEvaluator" autowire="byName" />
</beans>

这是我的acl-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:p="http://www.springframework.org/schema/p"
 xmlns:util="http://www.springframework.org/schema/util"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/util
   http://www.springframework.org/schema/util/spring-util-3.0.xsd">

    <!-- Declare a simple map containing all our roles -->
    <util:map id="permissionsMap">
         <entry key="ROLE_USER" value-ref="user"/>
     </util:map>

 <!-- Declare permissions for Admin
  Contains a map of objects and their associated allowed actions -->
 <bean id="user" class="code.permission.Permission" >
  <property name="objects">
   <map>
    <entry key="code.entities.MyEntity">
     <list>
      <value>READ</value>
     </list>
    </entry>
   </map>
  </property>
 </bean>

</beans>

这是mySecurity.xml

 <?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/security
           http://www.springframework.org/schema/security/spring-security-3.1.xsd">

  <!-- To enable Method Security Expressions and custom PermissionEvaluator
   we need to add the following -->
         <global-method-security pre-post-annotations="enabled">
                <expression-handler ref="expressionHandler" />
         </global-method-security>

 <!-- To use hasPermission() expressions, we have to configure a PermissionEvaluator -->
 <!-- See 15.3.2 Built-In Expression
   @http://static.springsource.org/spring-security/site/docs/3.0.x/reference/el-access.html#el-permission-evaluator -->
        <beans:bean id="expressionHandler"
            class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" name="expressionHandler" autowire="byName">
        <beans:property name="permissionEvaluator" ref="customPermissionEvaluator" />
        <beans:property name = "roleHierarchy" ref="roleHierarchy"/>
     </beans:bean>

 <!-- Declare a custom PermissionEvaluator interface -->
 <beans:bean class="code.permission.MyCustomPermissionEvaluator" id="customPermissionEvaluator" name="customPermissionEvaluator" autowire="byName" />

    <http auto-config="true" use-expressions="true">
    <intercept-url pattern="/index.jsp" access="permitAll" />
    <intercept-url pattern="/firstPage" access="hasRole('ROLE_USER')" />
    </http>

    <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="user" password="user" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

    <!-- http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.html -->
    <beans:bean id="roleHierarchy"  class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl" name="roleHierarchy" autowire="byName">
      <beans:property name="hierarchy">
         <beans:value>
             ROLE_USER
         </beans:value>
     </beans:property>
    </beans:bean>
 </beans:beans>

这是我的Permission.java     package code.permission;

import java.util.List;
import java.util.Map;

/**
 * Contains a map of objects and their associated allowed actions
 */
public class Permission {

 /**
  *  A Map containing a list of objects and their corresponding actions
  *  <p>
  *  String: key name of the object
  *  List<String>: a list of permissions
  */
  private Map<String, List<String>> objects;

 public Map<String, List<String>> getObjects() {
  return objects;
 }
 public void setObjects(Map<String, List<String>> objects) {
  this.objects = objects;
 }

}

这是myCustomPermissionEvaluator.java

package code.permission;

import java.io.Serializable;
import java.util.Collection;
import java.util.Map;

import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

import javax.annotation.Resource;

public class MyCustomPermissionEvaluator implements PermissionEvaluator {

  @Resource(name="permissionsMap")
   private Map permissionsMap;

 @Resource(name="roleHierarchy")
 private RoleHierarchy roleHierarchy;

 public boolean hasPermission(Authentication authentication,
   Object targetDomainObject, Object permission) {
     System.out.println("First hasPermission");

  String role = getRole(authentication);

  return hasPermission(role, permission, targetDomainObject);
 }

 /**
  * Another hasPermission signature. We will not implement this.
  */
 public boolean hasPermission(Authentication authentication,
    Serializable targetId, String targetType, Object permission) {

  return false;
 }

 /**
  * Retrieves the user's highest role
  */
 private String getRole(Authentication authentication) {
  String highestRole = null;

  try {
    Collection<GrantedAuthority> auths = (Collection<GrantedAuthority>)   roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
   for (GrantedAuthority auth: auths) {
    highestRole = auth.getAuthority();
    break;
   }

  } catch (Exception e) {

  }

  return highestRole;
 }

 private Boolean hasPermission(String role, Object permission, Object domain) {
     System.out.println("Second hasPermission");
  if ( permissionsMap.containsKey(role) ) {
        Permission userPermission = (Permission) permissionsMap.get(role);

  if ( userPermission.getObjects().containsKey(domain.getClass().getName())){

    for (String action: userPermission.getObjects().get(domain.getClass().getName()) ) {
      if (action.equals(permission)) {

       return true;
     }
    }
   }
  }

  return false;
 }
}

这是MyAction.java

package code.action;

import org.springframework.security.access.prepost.PreAuthorize;
import code.entities.MyEntity;

public class MyAction {
    @PreAuthorize("hasRole('ROLE_USER')")
    public String showPage(){
        System.out.println("in MyAction : showPage");
        MyEntity entity = new MyEntity();
        if(isAccessible(entity))
            return "success";
        else
            return "input";
    }
     @PreAuthorize("hasPermission(#entity,'WRITE')")
    public boolean isAccessible(MyEntity entity){
        System.out.println("in MyAction : isAccessible");
        return true;
    }
}

这里的任何专家都告诉我为什么这个hasPermission()无效?

1 个答案:

答案 0 :(得分:7)

它不起作用,因为Spring AOP只能触发bean之间的调用,但是如果你调用同一个bean的方法则不行。

因此,要么将isAccessible方法移动到其他bean,要么使用AspectJ而不是Spring Proxy AOP。

另一个想法是直接使用权限评估,而不是使用带注释的方法。 (但我不确切知道如何做到这一点。)