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