обеспечение безопасности API. Как проверить текущего пользователя, который хочет получить доступ к ресурсу - PullRequest
0 голосов
/ 18 июня 2020

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

Сначала позвольте мне рассказать потоку, когда пользователь получил токен с сервера,

Пользователь может зарегистрироваться или войти в систему, если все проверки верны, сервер ответит:

{
  "meta": {
    "issueDate": 1592078419167,
    "expToken": "10800000"
  },
  "payload": {
    "user": {
      "id": 3,
      "email": "new3@gmail.com",
      "username": "new3"
    },
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MywiZW1haWwiOiJuZXczQGdtYWlsLmNvbSIsInVzZXJuYW1lIjoibmV3MyIsImlhdCI6MTU5MjA3ODQxOSwiZXhwIjoxNTkyMDg5MjE5fQ.cjLgQjc2QbIhgumG2X2VsLk70c58F7NrKboYL2F2Sa0"
  }
}

затем с этим токеном он может выполнять операции CRUD, присоединяя его к заголовку как схему Authorization: 'bearer TOKEN'. С токеном на месте промежуточное ПО на сервере проверяет, не было ли оно подделано или истекло (я использую здесь JWT), если его срок истек или подделан, а затем ответ сервера с 401 unauthorized.

Но вот что я заметил. Допустим, у меня есть таблицы USERS и POSTS (1: N). User1 имеет 2 сообщения с идентификаторами 1 и 2 соответственно, затем другой пользователь регистрируется, позволяет называть его User2, User2 регистрируется, успешно получил токен, затем переходит на терминал, использует curl, отправляет запрос на маршрут api/post/1/edit, которого он не делает своя. Вот и моя проблема. Пользователь, знающий, как работает Интернет / API, может просто взять токен и получить доступ к любому ресурсу.

У меня есть несколько решений.

  1. создать промежуточное ПО, которое проверяет если пользователь владеет ресурсом, запрашивая базу данных. Но я не думаю, что это эффективное решение, потому что мне нужно запрашивать и делать это на другом контроллере, таком как users_controller, posts_controller, another_controller.

  2. вместо увеличения идентификатора я буду использовать UUID, поэтому всякий раз, когда они пытаются получить доступ к маршруту редактирования сообщений, они не могут легко определить идентификатор. как api/post/1akA13124S5129/edit <--- это сложно понять. </p>


Надеюсь, моя проблема ясна. Любые решения будут оценены. Огромное спасибо. <3 </p>


PS: Я пробовал на facebook, не работает. Я думаю, у них много токенов и куки. Кстати, я не использую и не включаю файлы cookie по любому запросу.

Ответы [ 2 ]

1 голос
/ 19 июня 2020

Вы придумали два стандартных решения. Первый - самый простой и распространенный. Со сколькими запросами в секунду вы обрабатываете проблемы с производительностью? Я бы сначала рассмотрел оптимизацию запросов к базе данных, прежде чем создавать более сложное решение.

Но в некоторых случаях второе решение («разреженный» идентификатор) очень удобно. Я использую их постоянно. Важно только то, что это означает, что знание идентификатора подразумевает доступ. Таким образом, у вас, вероятно, не может быть URL-адреса типа api/post/1akA13124S5129/edit. Как будет выглядеть URL-адрес "читать, но не редактировать"? Он не может включать "1akA13124S5129", поскольку любой, кто знает этот идентификатор, может редактировать сообщение, добавляя /edit.

Мой любимый способ использования «знание идентификатора предоставляет доступ» - использовать SHA-256 ha sh данных в качестве идентификатора. Это означает, что для того, чтобы угадать идентификатор, вам нужно уже знать его содержимое. Это очень хороший способ обрабатывать такие вещи, как изображения. Но это не работает для вещей, которые вы хотите редактировать, как это делаете вы здесь.

Если вы действительно не можете выполнять поиск в базе данных (а если нет, вам действительно следует расширить этот вопрос, чтобы объяснить свою проблему ), то есть много других подходов, но они сильно зависят от ваших конкретных требований. Например:

  • Если пользователи могут редактировать свои собственные сообщения, но любой может читать любое сообщение, тогда укажите URL-адрес для определения разрешений. Например: api/post/alice/1 может редактировать только Алиса.
  • Вместо использования JWT только для аутентификации (auth C), также используйте его для авторизации (authZ). Например, если вы хотите получить доступ к api/post/1/edit, сначала вы должны подключиться к серверу authZ и запросить JWT. Этот сервер выполнит поиск в базе данных, а затем предоставит вам JWT специально для этого URL-адреса (или вы можете выполнить пакетную обработку группы URL-адресов или группы разрешений, например «администратор»). Затем вы можете повторно использовать этот JWT много раз, и обслуживающая ресурсы сторона системы не должна повторно подтверждать ваши права доступа. Он может полагаться на JWT до истечения срока его действия. Это может значительно снизить нагрузку на базу данных.

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

1 голос
/ 18 июня 2020

Определенно номер один. Это то, что Facebook, StackExchange, Google, Microsoft и большинство популярных сайтов используют для защиты своего API.

Я буду использовать UUID, поэтому всякий раз, когда они пытаются получить доступ к сообщениям, редактируйте маршрут

Когда они вообще получили эти UUID? По сути, вы создаете один токен для каждого ресурса. Таким образом, когда пользователь просто хочет увидеть сегодняшние сообщения, ваш бэкэнд по-прежнему будет запрашивать базу данных для создания / выбора UUID для каждого сообщения, даже если пользователь вряд ли будет обновлять каждое отдельное сообщение, которое он ищет. . О, вы хотите отложить UUID до тех пор, пока пользователь не вызовет маршрут редактирования? Поскольку пользователю по-прежнему требуется , чтобы получить этот UUID в первую очередь, то это просто дополнительный шаг «передать UUID пользователю», который не добавляет безопасности.

Тогда это тоже становится головной болью, если ресурс не является полностью секретным и может использоваться только одним пользователем. На Facebook личное сообщение может быть удалено / отредактировано только отправителем, но другие могут комментировать или реагировать на него. Поскольку Facebook необходимо отслеживать, кто на что реагирует, они все равно будут проверять токен аутентификации и соотносить его с таблицей пользователей. Тем временем ваш метод UUID в конечном итоге приведет к созданию нескольких UUID для каждого отдельного пользователя, поэтому, если, скажем, сообщение просматривают сотни пользователей, вы в конечном итоге сохраните сотни UUID только для этого сообщения. Затем рассмотрите комментарии (которые могут быть удалены комментатором и создателем сообщения), сообщение страницы / группы (которое может быть удалено администратором страницы / группы) или даже этот самый сайт, где есть вопросы и ответы может редактировать кто угодно.

...