Кешируются ли результаты предварительно авторизованных аннотаций? - PullRequest
0 голосов
/ 21 февраля 2019

В Spring Boot кэшируются ли @PreAuthorize("@bean.checkAuthorization(#argument)") вызовы для каждого запроса?

В качестве минимального примера предположим, что @Controller имеет следующую конечную точку REST:

@GetMapping("/api/test") public String testAuthorization() {
    String argument;

    String foo = service.foo(argument);
    String bar = service.bar(argument); // same arguments
    return bar + foo;
}

и методы foo и bar в service определены следующим образом:

@PreAuthorize("@bean.checkAuthorization(#argument)")
public String foo(String argument) {
    return "hello";
}


@PreAuthorize("@bean.checkAuthorization(#argument)")
public String bar(String argument) {
    return "world";
}

Вариант использования. Учитывая, что Bean.checkAuthorization(argument)выполнение дорогостоящей функции ( например, , она делает вызов базы данных), но без сохранения состояния ( т.е. ее результат для данного аргумента не изменится при множественных вызовах), необходимо толькосделать звонок один раз за запрос.Следовательно, возможно ли кэшировать результат для всего запроса, но при этом убедиться, что проверка выполняется для каждого запроса?(без долгосрочного кэша)

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

Это не хорошая идея.

При реализации чего-то подобного вы становитесь уязвимыми для атаки отравления кэша;то есть вы подвергаете себя угрозе того, что любой, кто не авторизован через вашу базу данных, будет авторизован так, как вы этого не хотите.

предпочтительнее принятьнезначительное снижение производительности при определении того, должен ли пользователь иметь доступ к защищенному ресурсу, чем утечка этого ресурса.

Лучшим вариантом может быть изучение того, что делает вызов базы данных настолько дорогим, или убеждение бизнеса в том, чтоэто расходы, которые необходимо оплатить для защиты этого ресурса.

0 голосов
/ 22 февраля 2019

Просто включите кеширование: @EnableCaching и поместите @Cacheable("checkauth") поверх метода checkAuthorization.

Правка Я понял, что мой ответ не для запроса, так какКомментарий ниже заявлен.Определенно есть несколько причудливых способов сделать это, например, здесь: Кэширование по запросу с помощью Spring , который использует AOP.

Но так сложно!Просто представьте себе, что большинство запросов занимают меньше секунды для большинства современных веб-приложений, политика удержания которых @Cached(expire = 1, timeUnit = TimeUnit.MINUTES) сделает свое дело, предварительная оптимизация - это дьявол.

Но я считаю, что этот подход действительно нестандарт для такой стандартной проблемы.Вместо этого я предлагаю вам роли: FOO & BAR, которые позволят вам просто аннотировать ваши методы с помощью: hasRole('FOO'), hasRole('BAR').

@Service
public class MyUserDetailsService implements UserDetailsService {
 
    @Autowired
    private UserRepository userRepository;
 
    @Override
    public UserDetails loadUserByUsername(String username) {
        User user = userRepository.findByUsername(username);

        if (checkAuthorizationFoo(user)) user.addRole("FOO");
        if (checkAuthorizationBar(user)) user.addRole("BAR");

        return new user;
    }
}

@PreAuthorize("hasRole('FOO')")
public String foo(String argument) {

@PreAuthorize("hasRole('BAR')")
public String bar(String argument) {

Поймите, что это не такt lazy, и ваши checkAuthorization методы всегда вызываются, что является недостатком этого подхода.Вы могли бы сделать это лениво с небольшим количеством работы, вероятно, но снова просто будьте осторожны, сколько оптимизации вы выходите и делаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...