#acl #spring-el
#acl #spring-el
Вопрос:
Обновление от 27 октября
Следующий метод имеет аннотацию ACL на основе SpEL. Это предназначено для проверки того, имеет ли файловый объект fileId
разрешения Read
и Write
. Если файловый объект содержит любое из двух разрешений, ACL передается, в противном случае создается исключение.
@Component
public class ApiImpl {
@PreAuthorize("@acl.hasPermissions('File',{'Read','Write'}, #fileId)")
public FileListVO getFiles(String fileId) {
...
}
}
Аннотация находится через acl
компонент ниже.
public interface AclService {
boolean hasPermissions(String type, List<String> permissions, Object resource, Object... resourceContext);
}
@Component("acl")
public class AclServiceImpl implements AclService {
@Override
public boolean hasPermissions(String type, List<String> permissions, Object resource, Object... resourceContext) {
List<String> resourcePermissions = get permissions of resource
if (resourcePermissions contains any of permissions) {
return true;
}
throw exception here
}
}
Вопрос в том, что приведенное ниже выражение SpEL не может быть вычислено:
@PreAuthorize("@acl.hasPermissions('File',{'Read','Write'}, #fileId)")
java.lang.IllegalArgumentException: Failed to evaluate expression '@acl.hasPermissions('File',{'Read','Write'}, #fileId)'
There is a List<String> permissions in it. What is the correct expression for this?
Пожалуйста, обратите внимание, что throw exception
поведение в AclServiceImpl.hasPermissions()
устаревшем коде, которое я не хочу менять. @PreAuthorize("@acl.hasPermissions('File',{'Read','Write'}, #fileId)")
ожидается, что оно вернет true
исключение, не вызывающее исключение. Я знаю, что следующим вариантом может быть следующее,
public interface AclService {
boolean hasPermission(String type, String permission, Object resource, Object... resourceContext);
}
@Component("acl")
public class AclServiceImpl implements AclService {
@Override
public boolean hasPermission(String type, String permission, Object resource, Object... resourceContext) {
List<String> resourcePermissions = get permissions of resource
if (resourcePermissions contains permission) {
return true;
}
return false; // not throw exception
}
}
@Component
public class ApiImpl {
@PreAuthorize("@acl.hasPermissions('File','Read', #fileId)"
"|| @acl.hasPermissions('File','Write', #fileId)")
@PostMeetingTelemetry()
public FileListVO getFiles(String fileId) {
...
}
}
но мне просто интересно, как улучшить
@PreAuthorize("@acl.hasPermissions('File',{'Read','Write'}, #fileId)")
так что следующий код работает.
public interface AclService {
boolean hasPermissions(String type, List<String> permissions, Object resource, Object... resourceContext);
}
@Component("acl")
public class AclServiceImpl implements AclService {
@Override
public boolean hasPermissions(String type, List<String> permissions, Object resource, Object... resourceContext) {
List<String> resourcePermissions = get permissions of resource
if (resourcePermissions contains any of permissions) {
return true;
}
throw exception here
}
}
@Component
public class ApiImpl {
@PreAuthorize("@acl.hasPermissions('File',{'Read','Write'}, #fileId)")
public FileListVO getFiles(String fileId) {
...
}
}
Ответ №1:
здесь возникает исключение
Конечно, оценка завершается неудачей, если вы создаете там исключение.
Вместо этого вы должны вернуть false .
Комментарии:
1. Спасибо, @Gary! То, что я на самом деле спрашиваю, опубликовано ниже.
2. Не следует добавлять ответ для уточнения вопроса; вместо этого отредактируйте вопрос. Самое простое решение — написать компонент-оболочку вокруг существующего компонента ACL, который улавливает исключение и возвращает false. Невозможно перехватить исключение в самом SpEL.
@PreAuthorize("@aclWrapper.hasPermissions('File',{'Read','Write'}, #fileId)")
.3. Вопрос обновлен. Просто интересно, как улучшить
@PreAuthorize("@aclWrapper.hasPermissions('File',{'Read','Write'}, #fileId)")
… Я знаю@PreAuthorize("@acl.hasResPermissions('PostMeeting', new String[]{'Read','CO_Read'}, #meetingUUID)")
, что это тоже не работает, но каков правильный формат?4. То, что у вас отлично работает для меня, SpEL создает список<String> для второго аргумента. Я протестировал его как чистый SpEL (не в spring security), но это не должно иметь значения. Если у вас все еще возникают проблемы, я посмотрю завтра.
Ответ №2:
Со следующими изменениями это работает. Не уверен, что требуется 1-е изменение, но 2-е изменение обязательно.
- Заменить
List<String>
наString[]
дляpermissions
- Заменить
{'Read','Write'}
наnew String[]{'Read','Write'}
Перед
public interface AclService {
boolean hasPermissions(String type, List<String> permissions, Object resource, Object... resourceContext);
}
@Component("acl")
public class AclServiceImpl implements AclService {
@Override
public boolean hasPermissions(String type, List<String> permissions, Object resource, Object... resourceContext) {
List<String> resourcePermissions = get permissions of resource
if (resourcePermissions contains any of permissions) {
return true;
}
throw exception here
}
}
@Component
public class ApiImpl {
@PreAuthorize("@acl.hasPermissions('File',{'Read','Write'}, #fileId)")
@PostMeetingTelemetry()
public FileListVO getFiles(String fileId) {
...
}
}
После
public interface AclService {
// Replace List<String> with String[]
boolean hasPermissions(String type, String[] permissions, Object resource, Object... resourceContext);
}
@Component("acl")
public class AclServiceImpl implements AclService {
@Override
public boolean hasPermissions(String type, String[] permissions, Object resource, Object... resourceContext) {
List<String> resourcePermissions = get permissions of resource
if (resourcePermissions contains any of permissions) {
return true;
}
throw exception here
}
}
@Component
public class ApiImpl {
// Replace {'Read','Write'} with new String[]{'Read','Write'}
@PreAuthorize("@acl.hasPermissions('File',new String[]{'Read','Write'}, #fileId)")
@PostMeetingTelemetry()
public FileListVO getFiles(String fileId) {
...
}
}