Django开发——用户与认证

通过session,我们可以在多次浏览器请求中保持数据,接下来就是用session来处理用户登录了。当然我们还需要认证。
Django用户认证系统处理用户帐号,组,权限以及基于cookie的用户会话。这个系统被称为auth/auth (认证与授权)系统。
用户常见的两步处理:

  • 认证用户是否是他所宣称的用户
  • 验证用户是否拥有某种操作的授权

用户认证系统会包含以下部分:

  • 用户:在网站注册的人
  • 权限:用于标识用户是否可以执行某种造作标志
  • 组:一种可以将标记和权限用于多个用户的常用方法
  • Messages:向用户显示队列的系统消息的常用方法
    打开认证支持
    像session工具一样,认证支持也是一个Django应用,放在 django.contrib 中,所以也需要安装。 与session
    系统相似,它也是缺省安装的,但如果它已经被删除了,通过以下步骤也能重新安装上:
    1. 根据本章早前的部分确认已经安装了session 框架。 需要确认用户使用cookie,这样sesson 框架才能正
      常使用。
    2. 将 ‘django.contrib.auth’ 放在你的 INSTALLED_APPS 设置中,然后运行 manage.py syncdb 以创建对应的
      数据库表。
    3. 确认 SessionMiddleware 后面的 MIDDLEWARE_CLASSES 设置中包含
      ‘django.contrib.auth.middleware.AuthenticationMiddleware’ SessionMiddleware。
      这样安装后,我们就可以在视图(view)的函数中处理user了。 在视图中存取users,主要用 request.user ;这个对象表示当前已登录的用户。
      可以通过这种方式来判断是否登录:
if request.user.is_authenticated():
# Do something for authenticated users.
else:
# Do something for anonymous users.

使用User对象
User实例一般从request.user,或者是其他虾米哪即将要讨论的方法取得,它有很多属性和方法。AnonymoUser对象模拟了部分接口,但不是全部,在把它当成真正的user对象使用前得检查一下user.is_authenticated()。

User对象属性

属性 描述
username 必须的,不能多于30个字符,仅用字母数字字符
first_name 可选,少于等于30字符
last_name 可选,少于等于30字符
email 可选,邮件地址
password 必需,密码的哈希值
is_staff 布尔值,用户是否拥有网站的管理权限
is_active 布尔值,设置该账户是否可以登录。把该标志位置Flase而不是直接删除用户
is_superuser 布尔值,标识用户是否拥有所有权限,无需显式的权限分配定义
last_login 用户上次登录时间日期,默认为当前的日期
date_joined 帐号被创建的日期时间,当帐号被创建时,默认为当前日期

登录和退出
Django提供内置的视图函数用于处理登录和退出,先来看看怎么手工登录和退出。
认证给出的用户名和密码,使用authenticate()函数,它接受两个参数,用户名username和密码password,并在密码对给出的用户名合法的情况下返回一个User对象,如果密码不合法,将返回None。

>>> from django.contrib import auth
>>> user=auth.authenticate(username='john',password='1234')
>>> if user is not None:
...     print ('Correct!')
... else:
...     print('Invalid password')

authenticate()函数只是验证一个用户的证书,而要登录一个用户,使用login()。该函数接收一个HttpRequest对象和一个User对象作为参数并使用Django的会话session框架把该用户的ID保存在该会话中。
同时一个视图同时使用login和authenticate()函数

from django.contrib import auth
from django.http import HttpResponseRedirect

def lodin_view(request):
    username=request.POST.get('username','')
    password=request.POST.get('passwprd','')

    user=auth.authenticate(username=username,password=password)
    if user is not None and user.is_activate:
        #密码正确并且用户允许登录
        auth.login(request,user)

        #定向到登录成功的界面
        return HttpResponseRedirect('/account/loggedin')
    else:
        #显示错误
        return HttpResponseRedirect('/account/invalid')

注销用户,django.contrib.auth.logout(),它接受一个HttpRequest对象并且没有返回值。

from django.contrib import auth
from django.http import HttpResponseRedirect

def logout_view(request):
    auth.logout(request)

    return HttpResponseRedirect("/account/loggeout")

在实际中,一般不需要自己写登录登出函数;认证系统提供了一系列试图用拉uchuli登录和登出。使用认证视图的第一步是将它们写入URLconf中。

from django.contrib.auth import logout,login


urlpatterns = [
    url(r'^/accounts/login/$',login),
    url(r'^/accounts/logout/$',logout),
    ]

/accounts/login/和/accounts/logout/是Django提供的视图的默认URL。缺省情况下login视图渲染login.html模板可以通过视图额外参数template_name修改这个模板名。
限制以登录用户的访问
一个简单的原始方法是检查is_authenticated然后重定向到登陆页面。

from django.http import HttpResponseRedirect


def my_view(request):

    if not request.user.is_authenticated():

        return HttpResponseRedirect('/accounts/login/?next=%s' %request.path)

作为一个快捷方式,也可以使用便捷的装饰器login_required修饰符。

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):

    pass

login_required做的事情:

  • 如果用户没有登录,重定向到/accounts/login/,把当前绝对URL作为next在查询字符串中传递过去,例如:/accounts/login/?next=/polls/3/。
  • 如果用户已经登录,正常的执行视图函数,视图代码就可以假定用户已经登录。
    对通过测试的用户限制访问
    限制访问可以基于某种权限,某些检查或者为login视图提供不同的位置,这些实现方式大致相同。一般方法是直接在视图的request.user上运行检查。例如检查用户登录是否具有polls.can_vote权限:
def vote(request):
    if request.user.is_authenticated() and request.user.has_perm('polls.can_vote'):
        pass
    else:
        return HttpResponse("You can't vote in this poll" )

并且Django有称为user_passes_test的简洁方式。它接受参数然后为你指定的情况生成装饰器:

from django.contrib.auth.decorators import login_required, user_passes_test


def user_can_vote(user):

    return user.is_authenticated() and user.has_perm("polls.can_vote")


@user_passes_test(user_can_vote,login_url="/login/")
def vote(request):

    #这里可以假设一个登录的用户合格的权限

user_passes_test使用一个必须的参数:一个可调用的方法,当存在user对象并当此用户允许查看该页面时返回True。第二个可选参数login_url,它让你指定的登录页面的URL默认为/accounts/login/.如果用户没有通过测试,那么user_passes_test将把用户重定向到login_url。
既然检查用户是否有一个特殊权限时相对常见的任务,Django为这种情形提供了更简便的方法。

from django.contrib.auth.decorators import permission_required

@permission_required('poll.can_vote',login_url="/login/")
def vote(request):

    #...

限制通用视图的访问
在Django用户邮件列表中问道最多的问题是关于对通用视图的限制访问,为实现这个功能需要自己包装视图并且在URLconf中,将你自己的版本替换通用视图。

管理Users,Permissions,Groups

管理认证系统最简单的方法是通过管理界面。
创建用户

>>> from django.contrib.auth.models import User
>>> user=User.objects.create_user(username='john',
...                            email='[email protected]',
...                             password='123456')

user是User类的一个实例,准备用于向数据库中存储数据。ceate_user()函数并没有在数据库中创建记录,在保存数据之前,仍然可以继续修改它的属性值。
修改密码
使用set_password()来修改密码:

>>> user=User.objects.get(username='john')
>>>> print (user.password)
pbkdf2_sha256$36000$mtvBgyDPGq3H$OxZj+gWxM4t8NBxqCc6xu32Wzw1isGXjj2AYTuySbtY=
>>> user.set_password('goo joob')
>>> user.save()
>>> print (user.password)
pbkdf2_sha256$36000$x5ouXCAuq16T$7dNpMOsV1ha+rCYcNmOapsUiF5wxYrOHxwWr3TcA+0U=

保存的是密码的加入salt的hash值,所以不能直接编辑。
处理注册
我们可以使用这些底层来创建允许用户注册的视图。作为这个事情的最简化处理,可以提供一个小视图,提示一些必须的用户信息并创建这些用户。Django提供了也可用的内置表单。

from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response

def register(request):
    if request.method=='POST':
        form=UserCreationForm(request.POST)
        if form.is_valid():
            new_user=form.save()
            return HttpResponseRedirect('/books/')
    else:
        form=UserCreationForm()
    return render_to_response('registration/register.html',{'form':form,})

在模板中使用认证数据
当前登入的用户,以及他的权限可以通过RequestContext在模板中的context中使用。
当使用RequestContext时,当前用户存储在模板变量{{ user }}中:

{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
<p>Welcome, new user. Please log in.</p>
{% endif %}

这些用户的权限信息存储在{{ perms }}模板变量中。可以使用类似{{ perms.polls }}的形式来检查,对于某个特定的应用,一个用户是否具有任意权限;也可以使用{{ perms.polls.can_vote }}来检查一个用户是否具有特定的权限。
可以在模板中检查权限:

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

权限、组和消息

权限
权限可以很方便地标识用户和用户组可以执行的操作。它们被Django的admin管理站点所应用,你也可以在自己的代码中使用它们。
Django的admin站点如下使用权限:

  • 只有设置了add权限的用户才能使用添加表单,添加对象的视图。
  • 只有设置了change权限的用户才能使用变更列表,变更表格变更对象的对象。
  • 只有设置了delete权限的用户才能删除一个对象。
    权限时根据每一个类型的对象而设置的,并不具体到对象的特定实例。就跟用户一样,权限也就是Django模型中的django.contrib.auth.models。也可以通过Django的数据库API直接操作权限。会自动为每一个Django模型创建三个基本权限:增加、改变和删除。 当你运行 manage.py syncdb 命令时,这些权限被添加到 auth_permission 数据库表中。

    组提供了一种通用的方式来让你按照一定的权限规则和其他标签将用户分类。一个用户可以隶属于任何数量的组。
    在一个组的用户自动获取了赋予该组的权限。组也可以通过给定一些用户特殊的标记,和用户管理一样,admin接口是管理组的最简单方法。组也就是Django模型,因此可以使用Django的数据库API在底层访问这些组。
    消息
    消息系统会为给定的用户接收消息,每个消息都和一个user相关。在每个操作成功之后Django的admin管理接口就会使用消息机制。例如,当你创建一个对象,你会在admin页面的顶上看到The object was created successfully 的消息。
    也可以使用相同的API在你自己的应用中排队接收和显示消息。

  • 创建一条新的消息使用user.message_set.create(message=’message_text’)。

  • 要获得/删除消息,使用user.get_and_delete_messages()这会返回一个Message对象的列表,并且从队列中删除返回的项。
    例子:创建播放单以后,为用户保存了一条消息。
def create_playlist(request,songs):
    #给songs创建一个播放单
    request.user.message_set.create(
        message='Your playlist was added successfully.'
    )

    return render_to_response("playlists/create.html",
                              content_instance=RequestContext(request))

当使用RequestContext,当前用户以及它的消息就会以变量{{ messages }}出现在模板的context中。

{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}

需要注意的是RequestContext会在后台调用get_and_delete_messages,因此即使你没有使用显示它们,他们也会被删除掉。这个消息框架只能服务在用户数据库中存在的用户。如果要想匿名用户发送消息,请直接使用会话框架。

猜你喜欢

转载自blog.csdn.net/mashaokang1314/article/details/81836276