Spring REST secure УДАЛИТЬ только принадлежащий (ТОЛЬКО созданный конечным пользователем приложения) ресурс - PullRequest
0 голосов
/ 27 мая 2020

Я пытаюсь найти лучшее решение в том, как безопасно (только владельцем) УДАЛИТЬ ресурс REST.

ЦЕЛЬ: ресурс может быть удален только владельцем / создателем этого ресурса ( означает тот, который создал этот ресурс).

Помещения:

  1. Каждый раз, когда конечный пользователь приложения создает учетную запись клиента, он получает обратно токен JWT.

  2. Чтобы иметь доступ к ресурсу REST, клиент должен предоставить действующий JWT.

  3. Проверка правильности JWT выполняется для каждого входящего вызова через фильтр клиентов:

    @ Component publi c class JwtRequestFilter extends OncePerRequestFilter {

        @Autowired
        private ClientAuthService clientAuthService;
    
        @Autowired
        private JwtUtil jwtUtil;
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
                throws ServletException, IOException {
    
            final String authorizationHeaderDate = request.getHeader("Date");
    
            if (authorizationHeaderDate != null){
    
                if (DateTimeUtil.isLaterInMinThenNow(
                        LocalDateTime.parse(authorizationHeaderDate,
                                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), 2)) {
    
                    final String authorizationHeader = request.getHeader("Authorization");
    
                    String username = null;
                    String jwt = null;
    
                    if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
                        jwt = authorizationHeader.substring(7);
                        username = jwtUtil.extractUsername(jwt);
                    }
    
                    if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
    
                        UserDetails userDetails = this.clientAuthService.loadUserByUsername(username);
    
                        if (jwtUtil.validateToken(jwt, userDetails)) {
                            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken
                                    = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                            usernamePasswordAuthenticationToken
                                    .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                        }
                    }
                }
            }
    
            chain.doFilter(request, response);
        }
    
    }
    
  4. Текущая реализация DELETE Конечная точка REST:

    @DeleteMapping("/clients/{id}")
    public ResponseEntity<Client> deleteClientById(@PathVariable(required = true) Long id){
        return ResponseEntity.ok(clientService.deleteClientById(id));
    }
    

Разрешение, как будто каждый конечный пользователь, имеющий действующий JWT, может удалить другую клиентскую учетную запись конечного пользователя.

Для хакеру легко получить JWT, интуитивно настроить идентификатор клиента и удалить по одному, все l учетные записи клиентов

Вопрос: как я могу предотвратить такую ​​проблему безопасности?

1 Ответ

2 голосов
/ 27 мая 2020

Вы хотите использовать управление доступом на основе выражений Spring:

https://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html

Вы можете аннотировать свой метод конечной точки REST или метод службы и использовать выражения EL для авторизации ваш пользователь. Вот пример из документации Spring, который вы можете адаптировать:

@PreAuthorize("#n == authentication.name")
Contact findContactByName(@Param("n") String name);

Теперь - вы не спрашивали, но вам следует подумать о соответствии соглашению REST об использовании HTTP-глагола, который соответствует тому, что делает ваше действие (т.е. используйте HTTP-действия DELETE для запросов, которые удаляют ресурсы):

Не используйте службу REST, которая использует методы GET HTTP для удаления ресурсов - для всех, кто знает что-либо о REST, это не имеет смысла:

@GetMapping("/clients/{id}")

Должно быть

@DeleteMapping("/clients/{id}")

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