Python 社交网站中的授权
我需要完成以下与特权相关的工作: 我有3个用户:Python 社交网站中的授权,python,django,authorization,social-networking,Python,Django,Authorization,Social Networking,我需要完成以下与特权相关的工作: 我有3个用户: - 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
- 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
用户A
将用户B
作为联系人,但不是用户C
的联系人(用户B
和用户C
是联系人)
因此,用户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)
我有兴趣了解如何处理这些特权。我也在寻找任何有助于我起步的文档或文章。您基本上需要的是。但是带有“联系人中的联系人”的部分可能会导致非常复杂的sql查询。我建议你重新考虑这个要求。(我有很多我喜欢和信任的好朋友。但是他们有各种各样的奇怪的人作为朋友…不幸的是,Django的授权系统不允许您为每个对象分配权限,只允许为每个类分配权限。这里我假设您的每个“文档”都是一个模型类的实例 然而,有一些可重用的应用程序大大简化了这项任务。查看或处理对象(或行)级别的内容。可以包含“朋友的朋友”字段。这将是一个非常大的表(比如,200*200*N=40000*N…如果你对朋友没有限制,并且某人是100万人的朋友,也就是100万人有100万FoF),那么这将比每个视图访问数据库200次更容易。你需要的是一个根据每个用户网络而变化的表。标准
django.contrib.auth
模块中没有ACL和基于对象的权限。实际上,我已经在Django中实现了一个ACL,但它是基于类而不是基于对象的。在应用程序的上下文中,它的工作原理就像用户A
可以查看任何人的文档,只要他在某个授权组(比如管理员
组)中。但是,如果用户A
在用户B
的联系人组中,它可以像用户A
一样工作,可以查看用户B
的文档
我可以从定制的auth应用程序的模型结构方面解释如何做到这一点。用户
和权限
模型将与标准Django auth应用程序相同(您可以从中复制)。然后,您需要一个模型来表示不同级别的权限(每个人、联系人、联系人、我自己)。这样做很简单,只需向标准django auth groups模型添加另一个字段。此字段将是同一模型的外键,它将表示每个组将从中继承的组。现在模型看起来像这样
class SocialGroup(models.Model):
name = models.CharField(unique=True, max_length=150)
parent = models.ForeignKey('self')
现在,您可以添加关系,例如联系人
group,通过将每个人
group设置为联系人
组的父级,可以查看每个人
组可以查看的所有内容。请注意,与权限
模型没有外键关系。接下来,我们需要一种方法来指定用户和组之间的关系
class Relationship(models.Model):
user = models.ForeignKey(User)
related_user = models.ForeignKey(User)
related_by = models.ForeignKey(SocialGroup)
在这个模型中,我们可以说用户A
(相关用户)通过处于用户B
s联系人组中而与用户B
(用户)相关。然后我们需要一种为每个文档指定权限的方法
class DocumentPermissions(models.Model):
document = models.ForeignKey(Document)
group = models.ForeignKey(SocialGroup)
Permission = models.ForeignKey(Permission)
现在我们可以说联系人
组拥有可以查看文档B1
的权限。请注意,此模型应位于文档模型所在的任何位置,而不是在新的auth应用程序中的auth models.py。就这样,现在我们所要做的就是编写逻辑来查找给定用户对给定文档的权限。因此,当用户B
试图查看文档A1
时,我们需要做的是
- 首先检查文档属于哪个人(
用户A
)
- 然后查找所有者和试图从关系模型(联系人)访问文档的人之间的关系组
- 然后检查
DocumentPermissions
,查看该组或其继承的任何组是否具有查看文档的权限
此逻辑可以在Django的新身份验证后端(将使用我们的新身份验证模型)中实现,Django可以进入新的身份验证应用程序。您可以在标准中检查是否具有\u perm
功能。这就是你需要做的。所有的装饰器和其他东西仍然可以工作。一般的答案是找到文档所有者和给定联系人之间的距离。用计算机科学的术语来说,这是一个问题
上有一篇很好的文章介绍了一些SQL查询,介绍了这个主题。以下是如何将问题概念化,而不是试图总结整篇文章:
- 从一张空白的纸开始
- 在页面上为每个人(在本例中为用户a、B和C)的某处画一个点。在CS术语中,这是一个“节点”
- 从用户到其所有联系人绘制箭头。在CS术语中,这是“定向边”或“弧”。
- 这在问题中并不明确,但看起来用户C必须是用户B的联系人,或者是用户a的其他联系人中的另一个联系人(因为用户a可以读取C2和C4)
- 在本例中,您将从用户A->用户B和用户B->用户C中进行绘制
另一方面,如果“接触”是相互的,则可以绘制线段(或双向箭头)而不是箭头。在CS术语中,这将是一个“无向”与“定向”图。Facebook关系是一种无方向的关系;如果有人是我的朋友,那么我也是他们的朋友。相反,如果有人在我的Outlook通讯录中,我不一定在他们的通讯录中。所以这是一种定向关系
随着越来越多的用户添加到图形中,您会注意到用户的联系人距离您只有一步之遥,而他们的联系人距离您只有两步之遥。但你只能沿着箭头的方向行进
所以,联系人的问题是,“我该怎么做
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
SELECT count(*)
FROM Relationships "rel"
WHERE rel.userid = $document_owner_user_id
AND rel.contactid = $id_of_current_user
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