验证多级关系依赖关系的最佳方法 [英] Best method to verify multi-level relational dependencies

查看:111
本文介绍了验证多级关系依赖关系的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设您有实体A,B,C和D.

  • D与C有关
  • C与B有关
  • B与A有关

此外,如果用户拥有A ,则仅允许该用户在D上进行操作.

在应用程序中的特定状态下,您将包含指向访问D的页面的链接.因此,您将D的ID包含为GET或POST参数.

如果用户单击链接,则应用程序将检索D的ID并开始在D上进行操作.

简单的应用程序使用这样的URL,例如[模块化URL重写]:

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

如何验证是否允许用户在D上进行操作?

A)显而易见的解决方案是:给出D,找到C,然后找到B,最后找到A.如果链断了,访问D会被拒绝.不幸的是,这需要(如果实现得很简单)需要4个数据库访问权限,而不仅仅是A的访问权限.

B)另一种解决方案是将 D的ID在当前会话中保留在一组可访问的实体中,以供下一个呈现页面使用.

C)作为一种替代方法,可以以某种方式加密GET和POST参数.在每个页面请求上,第一个操作将是解密请求的参数.如果解密操作失败,则访问将被拒绝.

D),或者无限期散列所有页面中的所有链接,在会话中保留一个映射,该映射将哈希与URL关联,并且仅将哈希写入网页.

E)最后,您可以保留D中对A,B和C的引用,C中对A和B的引用,B中对A的引用.因此,在每个级别上,将是能够立即找到根实体.

在这种情况下,您有什么解决方案?为什么?

尽管我包括了PHP标记,但我不想将这个问题集中在一种语言上.我很乐意得到一般建议.或解决方案,这些方案已经在例如 ORM 层.

UPDATE-1

最后,我选择了 D).

一般原则:

确保以某种方式始终以安全/受信任的方式传递从属实体的ID.这样,第三方就无法更改其值.

详细信息:

此选项通过设计提供了许多好处:

首先,链接页面的ID或其他参数永远不会到达浏览器.代替

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

大多数页面都这样链接

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

要执行的下一页的所有参数完全保留在用户会话中.

由于页面的所有参数都保留在用户会话中,因此需要的检查要少得多.特别是,上面提到的关系依赖检查不再使用.如果用户会话中存在某些内容,则该内容是从先前的受信任的对话框步骤中放入的.

此外,甚至可以强制用户仅调用当前渲染页面上可用的那些链接.每次他们调用链接时,应用程序都可能使页面的所有其他链接无效.因此,用户将无法在多个窗口中打开页面并认为自己看到了应用程序的两个不同状态".如果他们两次调用链接,则该应用程序可能会显示错误消息.

最后,可以直接建立一个我称之为 sub-workflow 对话框的东西:您可以通过在会话的 continuation堆栈中推送当前页面的URL来启动该对话框 >,然后打开编辑对话框步骤.用户可以有序结束或有意取消对话工作流程.如果继续堆栈不为空,则取消工作流程链接可能会自动显示为用户选项.

通过在会话中的堆栈上保留连续性,可以将其与当前运行的对话框步骤完全隔离.对话步骤甚至不了解有关其调用者的任何信息.

通过将功能包装到一个小型管理器调用中,子流程最终将调用FlowManager :: finishFlow().此调用从堆栈中弹出一个继续,并将浏览器重定向到此页面-有效地返回到工作流开始的地方.

由于我们使用了一系列延续,所以甚至可以运行从属于其他子工作流的子工作流.

解决方案

显而易见的解决方案是:给定D,找到C,然后找到B,然后 最终找到A.如果链条在某处断裂,则访问D 拒绝了.不幸的是,这需要-如果实施得很简单-4 数据库访问,而不只是A的访问.

我想这可能是可能的.它部分取决于与...相关"的含义,但是假设使用相对简单的架构,我希望您能够在单个SQL语句中连接所有四个表.如果缺少链的一部分,查询将不返回任何行.

或者我想念什么吗?

Suppose you have entities A, B, C and D.

  • D relates to C
  • C relates to B
  • B relates to A

Furthermore, user is only allowed to operate on D, if user owns A.

At a certain state in an application, you include a link to a page, which accesses D. Thus, you includes D's ID as a GET or POST parameter.

If user clicks on the link, the application retrieves D's ID and begins to operate on D.

Simple apps use URLs like this [modulo URL-rewriting]:

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

How to verify if user is allowed to operate on D?

A) The obvious solution would be this: Given D, find C, then find B and eventually find A. If the chain breaks somewhere, access to D would be rejected. Unfortunately, this requires - if trivially implemented - 4 database accesses instead of just the one for A.

B) Another solution would be to keep D's ID in the current session in a set of accessible entities to be used by the next page to be rendered.

C) As an alternative, one could encrypt GET and POST parameters somehow. On each page request, the first operation would be to decrypt the request's parameters. If the decrypt operation fails, access would be denied.

D) Or, at infinitum, hash all links in all pages, keep a map in the session which associates the hashes with the URLs and write only hashes to webpages.

E) Finally, you could keep references to A, B and C in D, references to A and B in C, references to A in B. Thus, at each level, one would be able to find immediately the root entity.

What's your solution in such a situation? And why?

Although I included the PHP tag, I'm don't want to focus this question to a language. I'd be happy to get general proposals. Or solutions, which are already implemented in e.g. ORM layers.

UPDATE-1

Finally, I have chosen D).

General principle:

Ensure, that IDs of somehow subordinate entities always get passed in a secure/trusted way. In such a way, that a third party isn't able to change their values.

Details:

This option provides many benefits by design:

First, IDs or other parameters of the linked pages never reach the browser. Instead of

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

most pages gets linked like this

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

All parameters of the next page to be executed are fully kept inside the user's session.

Since all parameters of pages are kept inside the user's session, far less checking is needed. Especially, the above mentioned relational dependency checks aren't any longer of use. If something is in the user's session, it has been put from a previously trusted dialog step.

Moreover, one can even force the user to only call those link available on the currently rendered page. Each time they call a link, the app may invalidate all other links of the page. Thus users won't be able to open pages in several windows and think, that they see two different 'state' of the application. If they call a link twice, the app may present an error message.

Finally, one may directly establish something I'd call sub-workflow dialogs: You would start the dialog by pushing the current page's URL on a continuation stack in the session and opening the edit dialog step. User may either orderly end or intentionally cancel the dialog workflow. A cancel workflow link may automagically appear as a user option, if the continuation stack isn't empty.

By keeping the continuation on a stack in the session, it gets fully isolated from the currently running dialog step. The dialog step not even knows anything about its caller.

By wrapping the functionality inside a small manager calls, the sub-process finally calls FlowManager::finishFlow(). This call pops a continuation from the stack and redirects the browser to this page - effectively returning to the point, where the workflow started.

Since we use a stack of continuations, one could even run sub-workflows which are subordinate to other sub-workflows.

解决方案

The obvious solution would be this: Given D, find C, then find B and eventually find A. If the chain breaks somewhere, access to D would be rejected. Unfortunately, this requires - if trivially implemented - 4 database accesses instead of just the one for A.

I suppose that might be possible. It depends in part on what "relates to" means, but assuming a relatively straightforward schema, I'd expect you to be able to join all four tables in a single SQL statement. If part of the chain is missing, the query would return no rows.

Or am I missing something?

这篇关于验证多级关系依赖关系的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆