自定义权限评估程序Spring

时间:2017-05-26 20:48:58

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

我想创建一个自定义权限评估程序,以便使用自定义方法@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

2 个答案:

答案 0 :(得分:8)

如果没有其他配置,您无法使用非PermissionEvaluator成员的重载方法(如果您想重新配置PermissionEvaluator模式,请参阅this answer。)

默认情况下,

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";
    }
}

答案 1 :(得分:0)

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

检查-> @customerPermissionsEvaluator。

@RestController
class RestControllerToProtect {

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