我正在寻找其他人如何构建这一点的一些意见。我将提供基于类(django组)的视图。
例如,用户的组将确定他或她将访问哪些视图/模板。我正在考虑存储路径以查看表中的函数,以确定用户的链接栏将包含哪些内容。还可以存储过滤器规范以确定将填充这些模板的行。
一个很好的例子是医院护理单位。一个单位的护士无需看到整个医院的病人。他们只需要看病人。同一单位的医生也只需要看到这些患者,但他们应该能够获得更多的功能。
这是通过某些第三方应用程序完成的吗?那你怎么解决这个问题呢?
谢谢, 皮特
答案 0 :(得分:42)
Django已经拥有了一个群组和权限系统,这可能就足够了。
http://docs.djangoproject.com/en/dev/topics/auth/
通常在您的代码中检查用户是否拥有权限。用户拥有自己的权限以及他所属的组的权限。您可以从管理控制台轻松管理它。
您需要查看两个部分。
对于1.您可以检查装饰器中的权限:
from django.contrib.auth.decorators import permission_required
@permission_required('polls.can_vote')
def some_view(request):
对于2.当前登录用户的权限存储在模板变量{{perms}}中。此代码检查与上述相同的权限。
{% if perms.polls.can_vote %}
<a href="/vote">vote</a>
{% endif %}
要生成链接列表,您可以迭代user.get_all_permissions()并从字典中获取链接(或生成链接的函数):
def more_elaborate_list_of_links_for_a_perm(user):
return ["/link1", ...]
_LINKS = {
'polls.can_vote' : lambda u: ["/user/specific/link/" + u.id],
'polls.can_close': lambda u: ['/static/link/1', 'static/link/2'],
'polls.can_open' : more_elaborate_list_of_links_for_a_perm
}
def gen_links(user):
# get_all_permissions also gets permissions for users groups
perms = user.get_all_permissions()
return sum((_LINKS[p](user) for p in perms if p in _LINKS), [])
可能还有很多其他方法。
答案 1 :(得分:5)
Django中有一个关于基于角色的权限的新项目非常有趣: http://bitbucket.org/nabucosound/django-rbac
答案 2 :(得分:4)
我们遇到了类似的问题。 Django的团队并不适合这个,但是你可以把它们塞进去。
我们这样做的方式如下:
每个访问控制对象都与groups表具有ManyToMany关系。每组用于定义特定类型的权限(“可以查看患者基础知识”,“可以编辑患者联系信息”等)。用户被添加到他们应该拥有权限的组中(在您看到的只有这家医院的患者的例子中,您可能有一个“谷视图 - 医院”组。)
然后,当您向用户显示记录列表时,将根据两个组的组合进行过滤。用户必须具有查看给定对象的所有关联组权限。
如果您的系统需要它,您可以保留单独的ManyToMany否定权限或单独的读/写权限。您还可以定义一组元组(医生,护士),这些元组会导致查找过滤器检索实际的权限子集。
就链接栏问题而言,您可以使用相同的系统以编程方式生成这些 - 基于用户可以查看或编辑的对象类进行过滤,然后使用get_absolute_url()
类型函数(可能称之为get_index_url()
)以返回每类对象索引的链接。
因为所有这些都相当复杂,你可能最终想要为这些事情做一些级别的缓存,但是在你进行优化之前让它工作。它是可能的,并且它在代码中的含义不如单词。
答案 3 :(得分:2)
不久前我也遇到过类似的问题。我们的解决方案可以解决问题,但对于您的情况来说可能过于简单。像大家一样,我们使用django权限系统来控制用户与模型的交互。但是,我们不仅尝试对用户进行分组,还通过GenericForeignKey对对象进行分组。
我们建立了一个与自身相关联的模型,以便开发层次结构。
class Group( models.Model ):
name = models.CharField( ... )
parent = models.ForeignKey( 'self', blank=True, null=True)
content_type = models.ForeignKey( ContentType )
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey( 'content_type', 'object_id' )
...
为了使其工作,我们还创建了一个模型作为django用户模型的用户配置文件。它包含的是一个链接到上面的Group模型的ManyToManyField。这允许我们根据需要授予用户访问零个或多个组的权限。 (documentation)
class UserProfile( models.Model ):
user = models.ForeignKey( User, unique=True )
groups = models.ManyToManyField( Group )
...
这给了我们两全其美,让我们不要试图把所有东西都塞进django的许可系统。我正在使用这个基本设置来控制用户访问体育内容(一些用户可以访问整个联盟,一些只有一两个会议,一些只能访问各个团队),并且在这种情况下运行良好。它可能足以满足您的需求。
答案 4 :(得分:1)
如果您不需要真正的每对象ACL,那么您可以使用Django权限系统。要获取所有可用权限的列表:
from django.contrib.auth.models import Permission
perms = Permission.objects.all()
有一个API for other authentication and authorization sources,因此您无需坚持使用此权限表。
您可以根据此授权模型(RBAC)破解此Django系统以满足您的需求,或者您可以提出类似ACL的解决方案。
答案 5 :(得分:1)
在Pinot Noir葡萄酒专家的网站上,我们根据许多不同的标准创建了每个对象的访问权限。如果入站链接具有与特色酒庄的域名匹配的引用字段,则用户获得“酒厂标记”,其扩展到与该酒厂相关的所有文章,品尝笔记等。我们使用“命名代币”来品尝活动,并且可以访问网站的特定部分。我们甚至使用它来为搜索引擎蜘蛛授予某些类型的权限,然后确保来自这些搜索引擎的链接具有与蜘蛛相同的权限(即没有隐形游戏)。
简短版本是你可以创建一个类(我们称之为TokenBuckets,它们持有令牌),每个对象(在详细页面,或列表页面,或其他任何)可以询问用户的TokenBucket是否具有一定的访问级别是允许的。
基本上它是一种奇怪的ACL系统。创建机制并不难。所有的魔力都在于确定在什么情况下令牌会进入存储桶。
答案 6 :(得分:1)
此问题已在 2009年10月中提出,问题仍然存在于 2012年7月。
我搜索了一个好的基于角色的应用,并发现django-permission
是最佳结果。
我需要的三个重要功能是角色,查看装饰器和模板标签;显然django-permissions
拥有所有这些。请阅读docs以了解它的使用情况。
唯一的缺点是它正在开发中。
答案 7 :(得分:1)
您可以使用django用户角色
答案 8 :(得分:0)
我们使用角色基础系统来解决类似的问题。 基本上用户有权担任不同的角色。
查看函数已装饰:
def needs_capability(capability,redirect_to="/cms/"):
def view_func_wrapper(view_func):
def wrapped_view_func(request,*args,**kwargs):
if not request.role._can(capability):
return HttpResponseRedirect(redirect_to)
return view_func(request,*args,**kwargs)
return wrapped_view_func
return view_func_wrapper
魔法的其余部分位于request.role
属性中
设置在上下文处理器中。对于未洗过的群众,经过身份验证的用户获得了一个角色
一个DummyRole。
模板内部进一步限制了对信息的访问:
{% if not request.role.can.view_all_products %}
Lots of products, yeah!
{% endif %}
在我看来,这不是最干净的解决方案,但按预期工作。