Django用户认证系统 组与权限解析


Posted in Python onAugust 02, 2019

Django的权限系统很简单,它可以赋予users或groups中的users以权限。

Django admin后台就使用了该权限系统,不过也可以用到你自己的代码中。

User对象具有两个ManyToManyField字段,groups和user_permissions

groups = models.ManyToManyField(Group, verbose_name=_('groups'),
  blank=True, help_text=_('The groups this user belongs to. A user will '
              'get all permissions granted to each of '
              'their groups.'),
  related_name="user_set", related_query_name="user")
user_permissions = models.ManyToManyField(Permission,
  verbose_name=_('user permissions'), blank=True,
  help_text=_('Specific permissions for this user.'),
  related_name="user_set", related_query_name="user")

可以像其它的django Model一样来访问他们:

myuser.groups = [group_list]
myuser.groups.add(group, group, ...)
myuser.groups.remove(group, group, ...)
myuser.groups.clear()
myuser.user_permissions = [permission_list]
myuser.user_permissions.add(permission, permission, ...)
myuser.user_permissions.remove(permission, permission, ...)
myuser.user_permissions.clear()

权限Permissions

权限是作为一个Model存在的,建立一个权限就是创建一个Permission Model的实例。

@python_2_unicode_compatible
class Permission(models.Model):
  """
  The permissions system provides a way to assign permissions to specific
  users and groups of users.
 
  The permission system is used by the Django admin site, but may also be
  useful in your own code. The Django admin site uses permissions as follows:
 
    - The "add" permission limits the user's ability to view the "add" form
     and add an object.
    - The "change" permission limits a user's ability to view the change
     list, view the "change" form and change an object.
    - The "delete" permission limits the ability to delete an object.
 
  Permissions are set globally per type of object, not per specific object
  instance. It is possible to say "Mary may change news stories," but it's
  not currently possible to say "Mary may change news stories, but only the
  ones she created herself" or "Mary may only change news stories that have a
  certain status or publication date."
 
  Three basic permissions -- add, change and delete -- are automatically
  created for each Django model.
  """
  name = models.CharField(_('name'), max_length=255)
  content_type = models.ForeignKey(ContentType)
  codename = models.CharField(_('codename'), max_length=100)
  objects = PermissionManager()
 
  class Meta:
    verbose_name = _('permission')
    verbose_name_plural = _('permissions')
    unique_together = (('content_type', 'codename'),)
    ordering = ('content_type__app_label', 'content_type__model',
          'codename')
 
  def __str__(self):
    return "%s | %s | %s" % (
      six.text_type(self.content_type.app_label),
      six.text_type(self.content_type),
      six.text_type(self.name))
 
  def natural_key(self):
    return (self.codename,) + self.content_type.natural_key()
  natural_key.dependencies = ['contenttypes.contenttype']

字段fields

name:必需。50个字符或更少,例如,'Can Vote‘

content_type:必需,一个对于django_content_type数据库table的引用,table中含有每个应用中的Model的记录。

codename:必需,100个字符或更少,例如,'can_vote'。

如果要为某个Model创建权限:

from django.db import models
 
class Vote(models.Model):
  ... 
  class Meta:
    permissions = (("can_vote", "Can Vote"),)

如果这个Model在应用foo中,则权限表示为'foo.can_vote',检查某个用户是否具有权限myuser.has_perm('foo.can_vote')

默认权限default permissions

如果已经在 INSTALLED_APPS配置了django.contrib.auth,它会保证为installed applications中的每个Django Model创建3个缺省权限:add, change 和 delete。

这些权限会在你第一次运行 manage.py migrate(1.7之前为syncdb) 时创建。当时所有的models都会建立权限。在这之后创建的新models会在再次运行 manage.py migrate时创建这些默认权限。这些权限与admin管理界面中的创建,删除,修改行为是一一对应的。

假设你有一个应用 foo ,其中有一个模型 Bar, 你可以用下述方法来测试基本权限:

  • add: user.has_perm('foo.add_bar')
  • change: user.has_perm('foo.change_bar')
  • delete: user.has_perm('foo.delete_bar')

权限模型( Permission model)一般不直接使用。

组Groups

组也是作为Model存在的:

@python_2_unicode_compatible
class Group(models.Model):
  """
  Groups are a generic way of categorizing users to apply permissions, or
  some other label, to those users. A user can belong to any number of
  groups.
 
  A user in a group automatically has all the permissions granted to that
  group. For example, if the group Site editors has the permission
  can_edit_home_page, any user in that group will have that permission.
 
  Beyond permissions, groups are a convenient way to categorize users to
  apply some label, or extended functionality, to them. For example, you
  could create a group 'Special users', and you could write code that would
  do special things to those users -- such as giving them access to a
  members-only portion of your site, or sending them members-only email
  messages.
  """
  name = models.CharField(_('name'), max_length=80, unique=True)
  permissions = models.ManyToManyField(Permission,
    verbose_name=_('permissions'), blank=True)
 
  objects = GroupManager()
 
  class Meta:
    verbose_name = _('group')
    verbose_name_plural = _('groups')
 
  def __str__(self):
    return self.name
 
  def natural_key(self):
    return (self.name,)

字段fields:

name:必需,80个字符或更少,例如, 'Awesome Users'。

permissions:ManyToManyField to Permission

group.permissions = [permission_list]
group.permissions.add(permission, permission, ...)
group.permissions.remove(permission, permission, ...)
group.permissions.clear()

Programmatically creating permissions

除了可以使用Model meta来创建权限,也可以直接用代码创建。

例如,为myapp应用中的BlogPost模型创建一个can_publish权限:

from myapp.models import BlogPost
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
 
content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(codename='can_publish',
                    name='Can Publish Posts',
                    content_type=content_type)

权限可以被赋予一个User对象通过它的user_permissions属性或者赋予一个Group通过它的permissions属性。

权限缓存

User的权限检查时是可以被缓存的,如果一个新权限被赋予一个User,如果再立即检查是不会被检查出来的。最简单的方法是重新fetch User对象。

from django.contrib.auth.models import Permission, User
from django.shortcuts import get_object_or_404 
def user_gains_perms(request, user_id):
  user = get_object_or_404(User, pk=user_id)
  #权限检查会缓存现在的权限集
  user.has_perm('myapp.change_bar')
 
  permission = Permission.objects.get(codename='change_bar')
  user.user_permissions.add(permission) 
  # 检查权限缓存集
  user.has_perm('myapp.change_bar') # False 
  # 请求新实例
  user = get_object_or_404(User, pk=user_id) 
  # Permission cache is repopulated from the database
  user.has_perm('myapp.change_bar') # True 
  ...

权限装饰器

permission_required(perm[, login_url=None, raise_exception=False])

检查用户是否具有某个权限,类似于@login_required()

from django.contrib.auth.decorators import permission_required
@permission_required('polls.can_vote', login_url='/loginpage/')
def my_view(request):
  ...

模板中的权限

user的的权限保存在模板变量 {{ perms }}中,是django.contrib.auth.context_processors.PermWrapper实例。

{{ perms.foo }}

上面的单属性是User.has_module_perms的代理。如果user拥有foo中的任一权限,则为True

{{ perms.foo.can_vote }}

上面的两级属性查询是User.has_perm的代理,如果用户拥有foo.can_vote权限则为True。

例如:

{% if perms.foo %}
  <p>You have permission to do something in the foo app.</p>
  {% if perms.foo.can_vote %}
    <p>You can vote!</p>
  {% endif %}
  {% if perms.foo.can_drive %}
    <p>You can drive!</p>
  {% endif %}
{% else %}
  <p>You don't have permission to do anything in the foo app.</p>
{% endif %}

或者:

{% if 'foo' in perms %}
  {% if 'foo.can_vote' in perms %}
    <p>In lookup works, too.</p>
  {% endif %}
{% endif %}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
二种python发送邮件实例讲解(python发邮件附件可以使用email模块实现)
Dec 03 Python
python使用内存zipfile对象在内存中打包文件示例
Apr 30 Python
跟老齐学Python之再深点,更懂list
Sep 20 Python
开源软件包和环境管理系统Anaconda的安装使用
Sep 04 Python
Python之文字转图片方法
May 10 Python
查看django执行的sql语句及消耗时间的两种方法
May 29 Python
对Pandas DataFrame缺失值的查找与填充示例讲解
Nov 06 Python
pandas 根据列的值选取所有行的示例
Nov 07 Python
在python带权重的列表中随机取值的方法
Jan 23 Python
Python中三元表达式的几种写法介绍
Mar 04 Python
如何把python项目部署到linux服务器
Aug 26 Python
Python自动化测试基础必备知识点总结
Feb 07 Python
python3中eval函数用法使用简介
Aug 02 #Python
Django用户认证系统 Web请求中的认证解析
Aug 02 #Python
Django用户认证系统 User对象解析
Aug 02 #Python
浅谈python3中input输入的使用
Aug 02 #Python
Pycharm连接远程服务器并实现远程调试的实现
Aug 02 #Python
在PyCharm的 Terminal(终端)切换Python版本的方法
Aug 02 #Python
Django单元测试工具test client使用详解
Aug 02 #Python
You might like
在PHP的图形函数中显示汉字
2006/10/09 PHP
微信公众平台网页授权获取用户基本信息中授权回调域名设置的变动
2014/10/21 PHP
php rsa 加密,解密,签名,验签详解
2016/12/06 PHP
浅谈ThinkPHP5.0版本和ThinkPHP3.2版本的区别
2017/06/17 PHP
form自动提交实例讲解
2017/07/10 PHP
php使用pecl方式安装扩展操作示例
2019/08/12 PHP
Laravel5.1框架路由分组用法实例分析
2020/01/04 PHP
JsEasy简介 JsEasy是什么?与下载
2007/03/07 Javascript
取得窗口大小 兼容所有浏览器的js代码
2011/08/09 Javascript
JS实现至少包含字母、大小写数字、字符的密码等级的两种方法
2015/02/03 Javascript
JQuery标签页效果的两个实例讲解(4)
2015/09/17 Javascript
jQuery简单实现title提示效果示例
2016/08/01 Javascript
一篇文章让你彻底弄懂JS的事件冒泡和事件捕获
2017/08/14 Javascript
JavaScript实现的仿新浪微博原生态输入字数即时检查功能【兼容IE6】
2017/09/26 Javascript
微信小程序支付及退款流程详解
2017/11/30 Javascript
echarts设置图例颜色和地图底色的方法实例
2018/08/01 Javascript
vue.js与后台数据交互的实例讲解
2018/08/08 Javascript
微信小程序实现时间预约功能
2018/11/27 Javascript
解决ie11 SCRIPT5011:不能执行已释放Script的代码问题
2019/05/05 Javascript
js防抖函数和节流函数使用场景和实现区别示例分析
2020/04/11 Javascript
Vue+ElementUI 中级联选择器Bug问题的解决
2020/07/31 Javascript
[00:59]DOTA2荣耀之路1:Doom is back!weapon X!
2018/05/22 DOTA
Python 文件读写操作实例详解
2014/03/12 Python
python中使用enumerate函数遍历元素实例
2014/06/16 Python
python正则中最短匹配实现代码
2018/01/16 Python
python实现flappy bird小游戏
2018/12/24 Python
python-docx文件定位读取过程(尝试替换)
2020/02/13 Python
Python动态强类型解释型语言原理解析
2020/03/25 Python
html5本地存储 localStorage操作使用详解
2016/09/20 HTML / CSS
人力资源部培训专员岗位职责
2014/01/02 职场文书
企业宣传工作方案
2014/06/02 职场文书
党的群众教育实践活动实施方案
2014/06/12 职场文书
2019年学校消防安全责任书(2篇)
2019/10/09 职场文书
python实现web邮箱扫描的示例(附源码)
2021/03/30 Python
深入理解Vue的数据响应式
2021/05/15 Vue.js
68行Python代码实现带难度升级的贪吃蛇
2022/01/18 Python