Лучший метод проверки многоуровневых реляционных зависимостей


Предположим, у вас есть сущности A, B, C и D.

  • D относится к C
  • C относится к B
  • B относится к A

Кроме того, пользователю разрешается работать только с D, если пользователь владеет.

В определенном состоянии приложения вы включаете ссылку на страницу, которая обращается к D. Таким образом, вы включаете идентификатор D в качестве параметра GET или POST.

Если пользователь нажимает на ссылку, приложение получает идентификатор D и начинает работать D.

Простые приложения используют URL-адреса, подобные этому [переписывание URL по модулю]:

http://www.myServer.com/?action=1234&entity=D&ID=23

Как проверить, разрешено ли пользователю работать на D?

A) Очевидным решением было бы следующее: Учитывая D, найдите C, затем найдите B и в конечном итоге найдите A. Если где-то цепочка оборвется, доступ к D будет отклонен. К сожалению, для этого требуется - если это тривиально реализовано - 4 доступа к базе данных вместо одного для A.

Б) Другим решением было бы чтобы сохранить идентификатор D в текущем сеансе в наборе доступных объектов, которые будут использоваться следующей отображаемой страницей.

C) В качестве альтернативы можно каким-то образом зашифровать параметры GET и POST. При каждом запросе страницы первой операцией будет расшифровка параметров запроса. Если операция расшифровки завершится неудачно, доступ будет запрещен.

D) Или, в бесконечности, хэшируйте все ссылки на всех страницах, сохраняйте карту в сеансе, которая связывает хэши с URL-адресами и записывает только хэши на веб-страницы.

E) Наконец, вы могли бы сохранить ссылки на A, B и C в D, ссылки на A и B в C, ссылки на A в B. Таким образом, на каждом уровне можно было бы немедленно найти корневую сущность .

Каково ваше решение в такой ситуации? И почему?

Хотя я включил тег PHP, я не хочу фокусировать этот вопрос на языке. Я был бы рад получить общее предложения. Или решения, которые уже реализованы, например, в слоях ORM.

ОБНОВЛЕНИЕ-1

Наконец, я выбрал D).

Общий принцип:

Убедитесь, что идентификаторы каким-либо образом подчиненных объектов всегда передаются безопасным/надежным способом. Таким образом, чтобы третья сторона не могла изменить свои ценности.

Подробности:

Этот вариант обеспечивает множество преимуществ по дизайну:

Во-первых, идентификаторы или другие параметры связанных страниц никогда не попадают в браузер. Вместо

http://www.myServer.com/?action=1234&entity=D&ID=23

Большинство страниц связывается таким образом

http://www.myServer.com/?forwardHash=78sd7sdf98asd7ad5aa76asa4a465

Все параметры следующей выполняемой страницы полностью хранятся в сеансе пользователя.

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

Более того, можно даже заставить пользователя вызывать только те ссылки, которые доступны на текущей отображаемой странице . Каждый раз, когда они вызывают ссылку, приложение может аннулировать все остальные ссылки на странице. Таким образом, пользователи не смогут открывать страницы в нескольких окнах и думать, что они видят два разных "состояния" приложения. Если они дважды вызовут ссылку, приложение может выдать сообщение об ошибке.

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

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

Заключая функциональность в небольшие вызовы менеджера, подпроцесс, наконец, вызывает flowmanAger::finishflow(). Этот вызов извлекает продолжение из стека и перенаправляет браузер на эту страницу - фактически возвращаясь к точке, с которой начался рабочий процесс.

Поскольку мы используем стек продолжений, можно даже запустить подпроцессы, которые подчиненный другим подпроцессам.

Author: SteAp, 2011-07-22

2 answers

Очевидным решением было бы следующее: учитывая D, найдите C, затем найдите B и в конечном итоге найдите A. Если цепочка где-то оборвется, доступ к D будет отклонен. К сожалению, для этого требуется - если это тривиально реализовано - 4 доступа к базе данных вместо одного для A.

Я полагаю, что это возможно. Отчасти это зависит от того, что означает "относится к", но, предполагая относительно простую схему, я ожидаю, что вы сможете объединить все четыре таблицы в одном SQL заявление. Если часть цепочки отсутствует, запрос не вернет ни одной строки.

Или я что-то упускаю?

 2
Author: Mike Sherrill 'Cat Recall', 2011-07-22 00:35:54

Я не уверен, что понимаю, чего вы хотите достичь, но не можете ли вы использовать опцию A, чтобы проверить, разрешено ли пользователю работать с D только с одним доступом к базе данных?:

SELECT D.*
  FROM D
    JOIN C 
      ON C.id = D.cid
    JOIN B
      ON B.id = C.bid
    JOIN A.id = B.aid
WHERE A.ownedBy = @userID
  AND D.id = @idToBechecked  
 1
Author: ypercubeᵀᴹ, 2011-07-30 07:34:37