社交网络网站中的授权

11 投票
5 回答
950 浏览
提问于 2025-04-16 19:27

我需要完成一些关于权限的事情:

我有三个用户:

- User A
- User B
- User C

每个用户都有一些文件,并且这些文件有相应的访问设置:

- User A
    - Document A1, only allow contacts to view
    - Document A2, allow everyone to view
    - Document A3, allow no one to view except myself
    - Document A4, allow contacts, and contacts of contacts to view
- User B
    - Documents B1, B2, B3, B4 with similar privileges
- User C
    - Documents C1, C2, C3, C4 with similar privileges

User AUser B当作联系人,但User C不是User A的联系人(User BUser C是联系人)。

所以,User A可以查看以下内容:

- Document B1 (contacts can view)
- Document B2 (everyone can view) 
- Document B4 (contacts of contacts)
- Document C2 (everyone can view)
- Document C4 (contacts of contacts)

我想了解这些权限是怎么处理的。我也在寻找一些文档或文章,帮助我快速上手。

5 个回答

3

你基本上需要做的是限制只有通过测试的登录用户才能访问。不过,关于“朋友的朋友”的部分可能会导致非常复杂的sql查询。我建议你重新考虑一下这个需求。(我有很多我喜欢和信任的好朋友,但他们也有各种奇怪的人作为朋友……)

7

很遗憾,Django的权限系统不支持对每个对象单独设置权限,只能对整个类设置权限。在这里,我假设你每个“文档”都是一个模型类的实例。

不过,有一些可重用的应用程序可以大大简化这个任务。你可以看看 django-guardian 或者 其他一些可以在对象(或行)级别上工作的包

5

一般来说,我们需要找出文档拥有者和某个联系人之间的距离。在计算机科学中,这种关系可以用有向图来表示。

有一篇不错的文章,里面有一些SQL查询,讨论了这个话题,链接在这里:http://techportal.inviqa.com/2009/09/07/graphs-in-the-database-sql-meets-social-networks/。与其试图总结整篇文章,不如先理解这个问题的概念:

  • 先准备一张空白纸。
  • 在纸上为每个人(在这个例子中是用户A、B和C)画一个点。在计算机科学中,这个点叫做“节点”。
  • 从每个用户画一条箭头指向他们的所有联系人。在计算机科学中,这叫做“有向边”或“弧”。
    • 虽然问题中没有明确提到,但看起来用户C必须是用户B的联系人,或者是用户A的其他联系人之一(因为用户A可以看到C2和C4)。
    • 所以在这种情况下,你会从用户A画一条箭头指向用户B,再从用户B画一条箭头指向用户C。

顺便提一下,如果“联系人”是双向的,你可以画一条线段(或双向箭头)而不是单向箭头。在计算机科学中,这叫做“无向图”与“有向图”的区别。比如Facebook上的朋友关系就是无向的;如果某人是我的朋友,那我也是他们的朋友。相反,如果某人在我的Outlook通讯录里,我不一定在他们的通讯录里。这就是一种有向关系。

随着更多用户被添加到图中,你会发现一个用户的联系人距离他们只有一步,而联系人之中的联系人则距离他们有两步。但你只能沿着箭头的方向移动。

所以,联系人问题是:“我如何找到所有距离为一的节点?”而联系人之中的联系人的问题是:“我如何找到所有距离为二的节点?”虽然“二或更少”可能更合适,因为你会期望直接联系人能访问所有“联系人之中的联系人”的内容。

对于一般情况,文章中描述了一些SQL查询,可能会提供一些见解。但针对你的具体需求,我建议使用一些连接查询。

我们考虑一个Users表,主键是id,还有其他字段,以及一个HasContact表,只有两列:userIdcontactId。我们假设用户A的id是1,用户B是2,用户C是3。HasContact表中有行(1, 2)和(2, 3),表示上述关系。

一组相对简单的SQL连接查询可以生成所有朋友或所有朋友的朋友的列表。

以下查询将返回用户的所有联系人的ID:

SELECT contact.id
  FROM Users "user"
    LEFT JOIN Relationships "rel"
      ON user.id = rel.userid
    LEFT JOIN Users "contact"
      ON rel.contactId = contact.id
  WHERE user.id = $id_of_current_user

如果你知道用户的ID,授权查询会相对简单:

SELECT count(*)
  FROM Relationships "rel"
  WHERE rel.userid = $document_owner_user_id
    AND rel.contactid = $id_of_current_user

如果查询返回0,那就说明当前用户不是文档拥有者的联系人。

我们可以更新第二个查询,来判断一个用户是否是某个联系人的联系人:

SELECT count(*)
  FROM Relationships "rel_1"
    INNER JOIN Relationships "rel_2"
      ON rel_1.contactId = rel_2.userId
  WHERE rel_1.userid = $document_owner_user_id
    AND rel_2.contactid = $id_of_current_user

只要在关系表中存在($document_owner_user_id, X)(X, $id_of_current_user)这两个条目,这个查询就应该返回非零值。否则,它将返回零。

我知道这个回答比较长,也有点间接,如果你有任何问题,请随时评论。

撰写回答