自定义权限评估器 Spring
Custom Permission Evaluator Spring
我想创建一个自定义权限评估器,以便使用自定义方法@PreAuthorize REST 端点。
我将 Spring Boot 1.5.3 与网络和安全启动器一起使用。
我的进一步用例是检查登录用户是否有权查看指定的 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
您不能在没有额外配置的情况下使用不属于 PermissionEvaluator
的重载方法(如果您想重新配置 PermissionEvaluator
模式,请参阅 答案)。
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";
}
}
以下代码应该可以解决您的问题
检查 --> @customerPermissionsEvaluator。
@RestController
class RestControllerToProtect {
@PreAuthorize("@customPermissionsEvaluator.hasPermission(#id)")
@GetMapping
public String methodToProtect(String id) {
return "Authenticated";
}
}
我想创建一个自定义权限评估器,以便使用自定义方法@PreAuthorize REST 端点。 我将 Spring Boot 1.5.3 与网络和安全启动器一起使用。
我的进一步用例是检查登录用户是否有权查看指定的 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
您不能在没有额外配置的情况下使用不属于 PermissionEvaluator
的重载方法(如果您想重新配置 PermissionEvaluator
模式,请参阅
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";
}
}
以下代码应该可以解决您的问题
检查 --> @customerPermissionsEvaluator。
@RestController
class RestControllerToProtect {
@PreAuthorize("@customPermissionsEvaluator.hasPermission(#id)")
@GetMapping
public String methodToProtect(String id) {
return "Authenticated";
}
}