参考:http://www.cnblogs.com/esperyong/

参考:https://docs.djangoproject.com/en/1.8/topics/auth/default/#topic-authorization

在Django的世界中,在权限管理中有内置的Authentication系统。用来管理帐户,组,和许可。还有基于cookie的用户session。

django中内置的权限控制1-User Model


这篇blog主要用来探讨这套内置的Authentication系统。

Django内置的权限系统包括以下三个部分:
用户(Users)
许可(Permissions):用来定义一个用户(user)是否能够做某项任务(task)
组(Groups):一种可以批量分配许可到多个用户的通用方式

首先需要在Django中安装这个组件:
在settings.py配置好数据库连接,运行python manage.py syncdb 。这一步将生成管理界面使用的数据库表。
将'django.contrib.auth'和'django.contrib.contenttypes'放到settings.py中的INSTALLED_APPS中。(使用contenttypes的原因是auth中的Permission模型依赖于contenttypes)

我们可以执行python manage.py shell来启动命令行,对其中的一些API进行学习和使用。

>> User对象 <<

首先最重要的开始就是User模型

User模型对应于一个用户,一个帐户,位于'django.contrib.auth.models'模块中。
User对象有两个多对多的属性分别是:groups和user_permissions

>> 新建User对象 <<

 from django.contrib.auth.models import User
u = User.objects.create_user('test1','test1','aaa')

User对象的Manager,UserManager:
和其他的模型一样,User模型类的objects属性也是一个Manager对象,但是User的Manager对象是自定义的,增加了一些方法:
create_user(username,email=None,password=None)
该方法创建保存一个is_active=True的User对象并返回。username不能够为空,否则抛出ValueError异常。email和password都是可选的。email的domain部分会被自动转变为小写。password如果没有提供,则User对象的set_unusable_password()方法将会被调用。
make_random_password(length=10,allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')
该方法返回一个给定长度和允许字符集的密码。其中默认的allowed_chars有一些字符没有,比如i,l等等。

>> User对象的属性 <<:

  username:字符串类型。必填。30个字符以内。
  first_name:字符串类型。可选。30个字符以内。
  last_name:字符串类型。可选。30个字符以内。
  email:可选。
  password:明文密码的hash或者是某种元数据。该属性不应该直接赋值明文密码,而应该通过set_password()方法进行赋值,在后面有详细说明TODO。
  is_staff:Boolean类型。用这个来判断是否用户可以登录进入admin site。
  is_active:Boolean类型。用来判断该用户是否是可用激活状态。在删除一个帐户的时候,可以选择将这个属性置为False,而不是真正删除。这样如果应用有外键引用到这个用户,外键就不会被破坏。
  is_superuser:Boolean类型。该属性用来表示该用户拥有所有的许可,而无需明确的赋予给他。
  last_login:datetime类型。最近一次登陆时间。
  date_joined:datetime类型。创建时间。

可以在新建用户时直接使用这些属性:

 from django.contrib.auth.models import User
u = User.objects.create_user('test1','test1','aaa')
u.first_name='a'
u.first_name='b'
u.save()

>> 修改User对象 <<:

 from django.contrib.auth.models import User
u = User.objects.get(username__exact='test1')
u.username='test2'
u.save()

注意修改完对象属性需要u.save()。

千万不要直接给User的password属性赋值,应该用set_password()方法进行赋值。

Tips:这些用户属性就是将数据库中用户授权信息的赋值动作。

用python manage.py changepassword *username*来进行修改,需要输入两次密码。

>> User对象方法 <<

像set_password()一样,除了DjangoModel对象的通用方法之外,User对象有以下特有方法:
  is_anonymous():
    永远返回False.用来将User对象和AnonymousUser(未登录的匿名用户)对象作区分用的识别方法。通常,最好用is_authenticated()方法。
  is_authenticated():
    永远返回True。该方法不代表该用户有任何的许可,也不代表该用户是active的,而只是表明该用户提供了正确的username和password。
  get_full_name():
    返回一个字符串,是first_name和last_name中间加一个空格组成。
  set_password(raw_password):
    调用该方法时候传入一个明文密码,该方法会进行hash转换。该方法调用之后并不会保存User对象。
  check_password(raw_password):
    如果传入的明文密码是正确的返回True。该方法和set_password是一对,也会考虑hash转换。
  set_unusable_password():
    将用户设置为没有密码的状态。调用该方法后,check_password()方法将会永远返回false。但是如果,调用set_password()方法重新设置密码后,该方法将会失效,has_usable_password()也会返回True。
  has_usable_password():
    在调用set_unusable_password()方法之后,该方法返回False,正常情况下返回True。
  get_group_permissions(obj=None):
    返回该用户通过组所拥有的许可(字符串列表每一个代表一个许可)。obj如果指定,将会返回关于该对象的许可,而不是模型。
  get_all_permissions(obj=None):
    返回该用户所拥有的所有的许可,包括通过组的和通过用户赋予的许可。
  has_perm(perm,obj=None):
    如果用户有传入的perm,则返回True。perm可以是一个格式为:'<app label>.<permission codename>'的字符串。如果User对象为inactive,该方法永远返回False。和前面一样,如果传入obj,则判断该用户对于这个对象是否有这个许可。
  has_perms(perm_list,obj=None):
    和has_perm一样,不同的地方是第一个参数是一个perm列表,只有用户拥有传入的每一个perm,返回值才是True。
  has_module_perms(package_name):
    传入的是Django app label,按照'<app label>.<permission codename>'格式。当用户拥有该app label下面所有的perm时,返回值为True。如果用户为inactive,返回值永远为False。
  email_user(subject,message,from_email=None):
    发送一封邮件给这个用户,依靠的当然是该用户的email属性。如果from_email不提供的话,Django会使用settings中的DEFAULT_FROM_EMAIL发送。
  get_profile():
    返回一个和Site相关的profile对象,用来存储额外的用户信息。这个返回值会在另一片博文中详细描述。

django中内置的权限控制2-Login Logout


而在Web应用中,任何的权限系统要做的第一步就是用户识别,也就是我们常说的登陆(login)。只有正确的登陆校验,知道用户是谁了,才能够知道用户能干什么,那就是许可(Permission)需要负责解决的事情,而Group则是批量设置许可的时候的一个便利手段。

>> 请求用户是否登陆的验证 <<

django有一套方法,可以在每个view方法能够接收到的request对象中增加权限验证相关的方法。要做到这一点,首先需要:

在settings文件中对MIDDLEWARE_CLASSES变量增加上述两个Middleware类SessionMiddleware和AuthenticationMiddleware。

 MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.transaction.TransactionMiddleware',
)

在view中,我们就可以使用request.user获取当前的登陆用户User对象。如果当前用户没有登陆,那么request.user将会是我们之前所说的AnonymousUser对象。我们可以用User对象的is_authenticated()方法将这两者区分开来,我们可以使用django新建一个项目,在view中进行测试:

 def test(request):
if request.user.is_authenticated():
return render_to_response('test.html',{'User_status':'login'})
else:
return render_to_response('test.html',{'User_status':'no login'})

在相应的视图函数前面增加@login_required修饰符可以实现非登录用户禁止访问:

from django.contrib.auth.decorators import login_required

@login_required
def test(request):
...

1、如果用户没登录, 重定向到/accounts/login/(settings.LOGIN_URL),并且把当前绝对URL作为next参数用get方法传递过去

2、如果用户已登录, 正常地执行视图函数

>>authenticate验证<<

使用命令行可以进行测试,authenticate(username,password)函数需要两个参数username,password,如果校验通过则返回User对象,如果校验不通过返回None,例如:

from django.contrib.auth import authenticate, login

def my_view(request):
user = authenticate(username='root', password='admin')
if user is not None:
print "User ok"
else:
print "password err or no user"

>> login_required <<

定义:django.contrib.auth.decorators.login_required([redirect_field_name=REDIRECT_FIELD_NAME,login_url=None])

login_required方法接受两个参数:
redirect_field_name:默认值是next。用来定义登陆成功之后的跳回之前访问界面的url。
login_url:默认值是settings.LOGIN_URL。用来指定登陆界面的url。如果不传入改参数,就需要确保settings.LOGIN_URL的值是正确设置的。

 from django.contrib.auth.decorators import login_required

 @login_required(login_url='/admin/')
def test(request):
...

示例view:

from django.http import HttpResponse,HttpResponseRedirect
from django.shortcuts import render_to_response
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import * def webpage_login(request):
"""
页面 -> 登录
"""
if request.GET.get('next') == None:
next_path = '/index/'
else:
next_path = request.GET.get('next')
page = {'next': request.path + '?next=' + next_path}
if request.POST.get('user') and request.POST.get('password'):
user_str, passwd_str = request.POST.get('user'), request.POST.get('password')
if authenticate(username = user_str, password = passwd_str):
user_object = authenticate(username = user_str, password = passwd_str)
login(request, user_object)
return HttpResponseRedirect(request.GET.get('next'))
else:
return HttpResponse("没有用户或密码错误")
else:
return render_to_response('login.html', page)

示例template:

<body class="login-bg">
<div class="login-body">
<div class="login-heading">
<h1>Login</h1>
</div>
<div class="login-info">
<form action="{{ next }}" method="post">
<input type="text" class="user" name="user" placeholder="User" required="">
<input type="password" name="password" class="lock" placeholder="Password">
<input type="submit" name="Sign In" value="Login">
</form>
</div>
</div>
</body>

django中内置的权限控制3-许可(Permission) 和 用户组(Group)


>> 许可(Permissions)<<

当我们在django中安装好了auth应用之后,Django就会为每一个你安装的app中的Model创建三个权限:add/change/delete,执行python manage.py syncdb之后相应的数据会插入到数据库中的。每一次你执行syncdb,Django都会为每个用户给新出现的Model增加这三个权限。

例如,你创建了一个应用叫做school,里面有一个模型叫做StudyGroup,那么你可以用任何一个user对象执行下面的程序,其结果都返回True:

 user.hash_perm('school.add_studygroup')
user.hash_perm('school.change_studygroup')
user.hash_perm('school.delete_studygroup')

我们也可以自己定义一些许可,就是在Model类的meta属性中添加permissions定义。比方说,创建了一个模型类叫做Discussion,我们可以创建几个权限来对这个模型的权限许可进行控制,控制某些人可以发起讨论、发起回复,关闭讨论:

 class Discussion(models.Model):
...
class Meta:
permissions = (
("open_discussion", "Can create a discussion"),
("reply_discussion", "Can reply discussion"),
("close_discussion", "Can remove a discussion by setting its status as closed"),
)

执行manage.py syncdb就会把增加的权限信息录入到后台数据库。

通过某一个user的user_permissions属性,permission_1为auth_permission表中的id值:

 user.user_permissions.add(permission_1, permission_2, ...)

删除权限:

 user.user_permissions.remove(permission_1, permission_2, ...)

通过user的一个组,然后通过group的permissions属性:

 group.permissions.add(permission_1, permission_2, ...)

我们要判断一个用户是否有发讨论的权限,我们可以用下面的代码:

 user.has_perm('school.open_discussion')

Permission类和User类没什么特殊的,都是普通的DjangoModel。在第一篇文章中我们详细探讨了User模型的属性和方法。在这里我们探讨一下Permission模型和如何用编程的方式而不是通过预定义然后syncdb的方式创建permission。因为也许在某些时候,需要动态创建并分配权限。

也可以通过Permission.objects.create()方法添加对应app中models的权限,如下app为svn中的模型定义Project添加除默认三个权限外的权限:

 from svn.models import Project
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType content_type = ContentType.objects.get_for_model(Project)
permission = Permission.objects.create(codename='project_admin',
name='Department administrator',
content_type=content_type)

【Python】django权限管理的更多相关文章

  1. Django 权限管理(二)

    权限菜单展示 1.展示的效果 实现该效果,涉及到的核心点(突破点) 1. 权限分类: (1)菜单权限 (主要用来展示的权限(url)如查看权限 url,  如上图中的每个权限都归类为菜单权限,主要用来 ...

  2. django权限管理(一)

    权限:权限就是一个包含正则的url. Rbac 权限管理: Role-Based Access Control,基于角色的访问控制.用户通过角色与权限进行关联,一个用户可以有多个角色,一个角色可以有多 ...

  3. 一.8.django权限管理/drf权限管理

    1.什么是权限管理: .权限管理,一般指根据系统设置的安全规则或者安全策略,用户可以访问而且只能访问自己被授权的资源 .权限管理好比如钥匙,有了钥匙就能把门打开,但是权限设置是有级别之分的,假如这个系 ...

  4. Django 权限管理

    对于Django而言,虽然自带了一些基本的通用权限限制,但现实中,可能我们更希望自己去定义业务权限划分 Django对于权限这块的部分验证方法 user = request.user user.is_ ...

  5. django权限管理

    当我们为应用创建一个Models, 在同步到数据库里,django默认给了三个权限 ,就是 add, change, delete权限. 首先,我们创建一个perm_test的project, 然后再 ...

  6. Django权限管理测试

    测试内容:当我单击登录页面登录的时候页面会弹出当前用户的个人信息 当我点击提交的时候可以看到我当前用户的所有权限: 测试成功,接下来看一下后台的简单代码: class User(models.Mode ...

  7. python Django学生管理

    Django 学生管理系统 1. 一对一 班级  模态增加 编辑 <!DOCTYPE html> <html lang="en"> <head> ...

  8. Python Django主机管理

    1.新建一个django project项目 django-admin startproject DjangoWeb 2.新建app python manage.py startapp master ...

  9. Django之权限管理

    Django权限管理之初步完整版 项目背景:这是一个权限管理系统(给一些角色和他们的权限指URL和页面可以删除的按钮比如:增删改查) 使用到了中间件,和初始化权限,使用了admin的后台管理系统. 我 ...

随机推荐

  1. Android 自定义ScrollView 支持惯性滑动,惯性回弹效果。支持上拉加载更多

    先讲下原理: ScrollView的子View 主要分为3部分:head头部,滚动内容,fooder底部 我们实现惯性滑动,以及回弹,都是靠超过head或者fooder 就重新滚动到  ,内容的顶部或 ...

  2. DBA_Oracle LogMiner分析重做和归档日志(案例)

    2014-08-19 Created By BaoXinjian

  3. RMQ问题(线段树+ST算法)

    转载自:http://kmplayer.iteye.com/blog/575725 RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ ...

  4. 在JavaScript里嵌入大量字符串常量的方法

    [转]在JavaScript文件里嵌入大量字符串常量是经常遇到的事.有时为了省事,就把一些界面的HTML和CSS直接写在JS文件里.数量少还好,多的话就密密麻麻的一坨文字,讲究美观的文艺青年们,会用大 ...

  5. 程序进入 EXPORT App_Fault_ISR的原因及措施:

    最近再UCOSIII+LPC1768上移植modbus,在定时器初始化部分竟然跑飞进入 EXPORT  App_Fault_ISR,查资料.逛论坛.问大牛都没有解决,最后发现竟然是犹豫一个低级失误引起 ...

  6. IP地址漂移的实现与原理

    当前备份软件比较流行,其中用到的关键技术是IP 地址漂移, 实际上IP地址漂移技术是利用共享的“虚拟”IP地址,当本地进行节点切换与路由切换,使另一端的发送和收方端没有感觉到本地节点地址有变化,保证了 ...

  7. java反射生成ORM

    package com.wzh.jdbc; import java.lang.reflect.Field;import java.sql.Connection;import java.sql.Prep ...

  8. vb eof详解

    源地址:https://zhidao.baidu.com/question/87122186.html?qbl=relate_question_1&word=eof%20sql&ski ...

  9. substr

    substr(string,start,length) string - 指定的要截取的字符串 start - 必需,规定在字符串的何处开始 正数 - 在字符串的指定位置开始 负数 - 在从字符串结尾 ...

  10. maven项目导入报错

    极大可能是仓库设置问题