【问题标题】:Custom Permission Evaluator Spring自定义权限评估器 Spring
【发布时间】:2017-10-27 20:10:20
【问题描述】:

我想创建一个自定义权限评估器,以便使用自定义方法@PreAuthorize REST 端点。 我将 Spring Boot 1.5.3 与 Web 和安全启动器一起使用。

我的进一步用例是检查登录的用户是否有权查看指定的 id。

调用 REST 端点时,我收到以下错误:

org.springframework.expression.spel.SpelEvaluationException: EL1004E: Method call: Method hasPermission(null) cannot be found on org.springframework.security.access.expression.method.MethodSecurityExpressionRoot type

我的自定义权限评估器:

@Component
class CustomPermissionsEvaluator implements PermissionEvaluator {

    public boolean hasPermission(String id) {
        return id.equals("correct");
    }

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        return false;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        return false;
    }
}

我的安全配置:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
class SecurityConfig extends GlobalMethodSecurityConfiguration {

    @Override
    public MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler methodSecurityExpressionHandler = new DefaultMethodSecurityExpressionHandler();
        methodSecurityExpressionHandler.setPermissionEvaluator(new CompanyPermissionsEvaluator());
        return methodSecurityExpressionHandler;
    }
}

我的休息控制器:

@RestController
class RestControllerToProtect {

    @PreAuthorize("hasPermission(#id)")
    @GetMapping
    public String methodToProtect(String id) {
        return "Authenticated";
    }
}

堆栈跟踪:

org.springframework.expression.spel.SpelEvaluationException: EL1004E:
Method call: Method hasPermission(null) cannot be found on
org.springframework.security.access.expression.method.MethodSecurityExpressionRoot type

【问题讨论】:

    标签: java spring-boot spring-security spring-rest


    【解决方案1】:

    如果您想重新配置PermissionEvaluator 模式,则不能使用不是PermissionEvaluator 成员的重载方法(请参阅this 答案)。

    hasPermission 调用默认应匹配以下签名之一:

    hasPermission(Authentication authentication, Object targetDomainObject, Object permission);
    
    hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission);
    

    例子:

    public class CustomPermissionEvaluator implements PermissionEvaluator {
    
        private Logger log = LoggerFactory.getLogger(CustomPermissionEvaluator.class);
    
        @Override
        public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
            CustomUserDetails customUserDetails = (CustomUserDetails) authentication.getPrincipal();
            AbstractEntity abstractEntity = (AbstractEntity) targetDomainObject;
            log.debug("User {} trying to access {}-{} with permission {}",
                    customUserDetails.getUsername(),
                    abstractEntity.getClass().getSimpleName(),
                    abstractEntity.getId(),
                    permission.toString());
            return false;
        }
    
        @Override
        public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
            CustomUserDetails customUserDetails = (CustomUserDetails) authentication.getPrincipal();
            log.debug("User {} trying to access {}-{} with permission {}",
                    customUserDetails.getUsername(),
                    targetType,
                    targetId,
                    permission.toString());
            return false;
        }
    }
    

    控制器:

    @RestController
    public class RestControllerToProtect {
        // passing targetDomainObject and permission, authentication is detected by SecurityExpressionRoot
        @PreAuthorize("hasPermission(#abstractEntity, 'create')")
        public String methodToProtect(@RequestBody AbstractEntity abstractEntity) {
            return "Authenticated";
        }
    }
    

    【讨论】:

      【解决方案2】:

      以下代码应该可以解决您的问题

      检查 --> @customerPermissionsEvaluator。

      @RestController
      class RestControllerToProtect {
      
          @PreAuthorize("@customPermissionsEvaluator.hasPermission(#id)")
          @GetMapping
          public String methodToProtect(String id) {
              return "Authenticated";
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2014-01-28
        • 1970-01-01
        • 2015-08-18
        • 1970-01-01
        • 2016-01-04
        • 1970-01-01
        • 2018-02-17
        • 2016-03-29
        • 1970-01-01
        相关资源
        最近更新 更多