【Python】django权限管理

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

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

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

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


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

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

首先须要在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进行学习和使用。cookie

 

>> User对象 <<session

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

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

 

>> 新建User对象 <<

1 from django.contrib.auth.models import User
2 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类型。建立时间。

能够在新建用户时直接使用这些属性:

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

 

>> 修改User对象 <<:

1 from django.contrib.auth.models import User
2 u = User.objects.get(username__exact='test1')
3 u.username='test2'
4 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。

1 MIDDLEWARE_CLASSES = (
2     'django.contrib.sessions.middleware.SessionMiddleware',
3     'django.middleware.locale.LocaleMiddleware',
4     'django.middleware.common.CommonMiddleware',
5     'django.middleware.csrf.CsrfViewMiddleware',
6     'django.contrib.auth.middleware.AuthenticationMiddleware',
7     'django.contrib.messages.middleware.MessageMiddleware',
8     'django.middleware.transaction.TransactionMiddleware',
9 )

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

1 def test(request):
2     if request.user.is_authenticated():
3         return render_to_response('test.html',{'User_status':'login'})
4     else:
5         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):
    ...

一、若是用户没登陆, 重定向到/accounts/login/(settings.LOGIN_URL),而且把当前绝对URL做为next参数用get方法传递过去

二、若是用户已登陆, 正常地执行视图函数

 

>>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的值是正确设置的。

1 from django.contrib.auth.decorators import login_required
2  
3 @login_required(login_url='/admin/')
4 def test(request):
5     ...

示例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:

1 user.hash_perm('school.add_studygroup')
2 user.hash_perm('school.change_studygroup')
3 user.hash_perm('school.delete_studygroup')

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

1 class Discussion(models.Model):
2     ...
3     class Meta:
4         permissions = (
5             ("open_discussion", "Can create a discussion"),
6             ("reply_discussion", "Can reply discussion"),
7             ("close_discussion", "Can remove a discussion by setting its status as closed"),
8         )

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

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

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

删除权限:

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

经过user的一个组,而后经过group的permissions属性:

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

咱们要判断一个用户是否有发讨论的权限,咱们能够用下面的代码:

1 user.has_perm('school.open_discussion')

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

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

1 from svn.models import Project
2 from django.contrib.auth.models import Group, Permission
3 from django.contrib.contenttypes.models import ContentType
4 
5 content_type = ContentType.objects.get_for_model(Project)
6 permission = Permission.objects.create(codename='project_admin',
7                                        name='Department administrator',
8                                        content_type=content_type)
相关文章
相关标签/搜索