Нужны данные из базы данных для использования в безопасности на уровне метода SpEL.

Я хотел бы использовать SpEL для обеспечения безопасности на уровне метода. Я столкнулся с проблемой, когда данных, переданных методу, недостаточно, чтобы определить, есть ли у пользователя доступ. Вот пример

@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
@ResponseStatus(HttpStatus.NO_CONTENT)
@PreAuthorize("@securityService.isAllowedAccessByCurrentUser(#.id)")
public void delete(@PathVariable("id") final Long id) {
    service.delete(id);
}

Здесь переменная id — это идентификатор некоторого объекта. Чтобы получить идентификатор владельца объекта (это то, что я хочу передать в выражении spel), мне нужно сделать что-то вроде:

service.findOne(id).getUser().getId();

Как я могу получить этот идентификатор и использовать его в выражении SpEL?


person yasgur99    schedule 09.07.2019    source источник


Ответы (1)


Зачем надо так сложно? Вы можете просто создать другой метод, чтобы специально проверить, может ли текущий пользователь удалить объект с данным идентификатором объекта, и сделать так, чтобы @PreAuthorize ссылался на этот метод:

@Service
public class SecurityService{

    @Autowired
    private Service service

    boolean isAllowToDeleteSomeObject(Long objectId){

       SomeObject anObject = service.findOne(objectId);

      //You should able to get the current user Id by SecurityContextHolder.getContext().getAuthentication(). 
      //getCurrentUserId() simply encapsulate such codes for convenient.
       Long currentUserId = getCurrentUserId();

       if(anObject.getUser().getId().equals(currentUserId)){
         return true;
       }else{
         return false;
       }
   }
}

Затем вы можете обратиться к этому методу в SpEL:

@PreAuthorize("@securityService.isAllowToDeleteSomeObject(#.id)")
public void delete(@PathVariable("id") final Long id) {   
}
person Ken Chan    schedule 10.07.2019
comment
Это хорошее решение, но с трудом удается поддерживать модульность по мере роста системы. Причина, по которой это было сложно, заключается в том, что у меня есть около 50 объектов, которые удаляются аналогичным, но не точным образом. В приведенном выше решении это будет означать, что у меня есть 50 автоподключенных сервисов. Было бы лучше сделать эти 50 автосвязей или каким-то образом создать интерфейс для каждого объекта, который необходимо удалить, и реализовать этот метод в самом объекте? - person yasgur99; 10.07.2019