Django会话,用户和注册之用户认证

Django会话,用户和注册之用户认证

通过session,我们可以在多次浏览器请求中保持数据, 接下来的部分就是用session来处理用户登录了。 当然,不能仅凭用户的一面之词,我们就相信,所以我们需要认证。

当然了,Django 也提供了工具来处理这样的常见任务(就像其他常见任务一样)。 Django 用户认证系统处理用户帐号,组,权限以及基于cookie的用户会话。 这个系统一般被称为 auth/auth (认证与授权)系统。 这个系统的名称同时也表明了用户常见的两步处理。 我们需要

1验证 (认证) 用户是否是他所宣称的用户(一般通过查询数据库验证其用户名和密码)

2验证用户是否拥有执行某种操作的 授权 (通常会通过检查一个权限表来确认)根据这些需求,Django 认证/授权 系统会包含以下的部分:

3用户 : 在网站注册的人

4权限 : 用于标识用户是否可以执行某种操作的二进制(yes/no)标志

5 组 :一种可以将标记和权限应用于多个用户的常用方法

6 Messages : 向用户显示队列式的系统消息的常用方法

这些在admin的管理界面中都可以看到,只不过在admin中我们是通过后台系统直接管理这些用户的。现在我们来看下如何通过User对象来进行管理

来进行测试下。首先我们在admin界面没有进行登录。我们进行测试

def function_test(request):
    print request.user,request.user.is_authenticated()

得到的结果是:

AnonymousUser False

也就是个匿名用户。且认证不通过。

然后我们紧接着在admin上进行登录。这个时候的打印。得到登录的用户以及验证通过的标识

zhf True

然后在浏览器上进行查看,发现多了一个sessionid,这表明在登录成功后会存储一个session值便于后续的识别

Django会话,用户和注册之用户认证

User实例从request.user获得,下面来看下User实例有哪些属性和方法

属性:

Username:必需的,不能多于30个字符。 仅用字母数字式字符(字母、数字和下划线)。

first_name:可选; 少于等于30字符。

last_name:可选; 少于等于30字符

email:可选。 邮件地址。

Passwor: 必需的。 密码的哈希值(Django不储存原始密码)。 See the Passwords section for more about this value.

is_staff: 布尔值。 用户是否拥有网站的管理权限。

is_active: 布尔值. 设置该账户是否可以登录。 把该标志位置为False而不是直接删除账户

is_superuser: 布尔值 标识用户是否拥有所有权限,无需显式地权限分配定义。

last_login: 用户上次登录的时间日期。 它被默认设置为当前的日期/时间。

date_joined: 账号被创建的日期时间 当账号被创建时,它被默认设置为当前的日期/时间。

方法:

is_authenticated():对于真实的User对象,总是返回 `` True`` 。   这是一个分辨用户是否已被鉴证的方法。 它并不意味着任何权限,也不检查用户是否仍是活动的。 它仅说明此用户已被成功鉴证  

is_anonymous: 对于AnonymousUser`` 对象返回True(对于真实的User对象返回False)  总的来说,比起这个方法,你应该倾向于使用is_authenticated()方法   

get_full_name:返回first_name加上last_name,中间插入一个空格

set_password: 设定用户密码为指定字符串(自动处理成哈希串)。 实际上没有保存User对象       

check_password(passwd) : 如果指定的字符串与用户密码匹配则返回True。 比较时会使用密码哈希表        

get_group_permissions:返回一个用户通过其所属组获得的权限字符串列表    

get_all_permissions():返回一个用户通过其所属组以及自身权限所获得的权限字符串列表

has_perm(perm):如果用户有指定的权限,则返回True ,此时perm的格式是"package.codename"。如果用户已不活动,此方法总是返回False

比如修改密码,通常都是在admin后台界面完成,不过也可以通过程序修改密码。使用set_password()

from django.contrib.auth.models import User
u = User.objects.get(username='zhf')
u.set_password('new password')
u.save()
 
介绍完了User对象实例,我们来看下再登录方面的应用
登录:
login():

从视图中登入一个用户,请使用login()。它接受一个HttpRequest对象和一个User对象。login()使用Django的session框架来将用户的ID保存在session中。注意任何在匿名会话中设置的数据都会在用户登入后的会话中都会记住。

下面的示例演示如何使用authenticate()login():建立一个简单的用户登录系统:

login.html:

<form action="/login/" method = 'post'>
    {% csrf_token %}
    <div>
    用户名:<input type="text" class="form-control" name="username" placeholder="请输入用户名">
        </div>
    <div>
    密码:<input type="text" class="form-control" name="password" placeholder="请输入密码">
        </div>
    <div>
    <input type="submit" value = "ok"/>
         </div>
</form>
 
Index1.html:
<div>
   <h1>welcome {{username}}</h1>
   <a href="/logout">logout</a>
</div>
 
Views.py中的处理函数:
from django.contrib import auth
def login(request):
    username=request.POST['username']
    password=request.POST['password']
    user=auth.authenticate(username=username,password=password)
    if user is not None and user.is_active:
        auth.login(request,user)
        return HttpResponseRedirect("/index1/")
    else:
        return HttpResponse('error user')
 
def logout(request):
    auth.logout(request)
    return HttpResponseRedirect("/index1/")

def index1(request):
    print request.session.get('_auth_user_hash')
    print request.session.get('_auth_user_backend')
    print request.session.get('_auth_user_id')
    user=request.user
    return render(request,'index.html',{'username':str(user)})
首先进入登录界面。输入用户名和密码

Django会话,用户和注册之用户认证

会自动跳转到index1的界面显示登录的用户名

Django会话,用户和注册之用户认证

对应的sessionid

Django会话,用户和注册之用户认证

点击logout后退出

Django会话,用户和注册之用户认证

此时的sessionid也同时被删除了

Django会话,用户和注册之用户认证

来看下代码的运行过程:

1 首先在login之前调用authenticate进行认证。
2 认证通过后运行login函数,login函数的作用是将用户名写入session中并生成sessionid发送给客户端
3 logout的作用就是清空对应session的数据

前面介绍了用户的登录过程,如果用户已经登录,那么就可以查看网站对于注册用户开放的权限,如果是未登录,再查看这些内容的时候就必须先跳到登录的界面进行登录后才可以。也就是我们必须限制用户对于页面的访问。最简单的方法就是在每个页面的处理函数中加入验证功能。当没有登录的时候,重定向登录的界面进行登录

def my_view(request):
    if not request.user.is_authenticated():
        return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))

但每个函数都加上这个判断也太麻烦了,幸好django给我们提供了装饰器函数login_required。

@login_required()
def preview(request):
    return render(request,'content.html')

login_required()完成下面的事情:

1 如果用户没有登入,则重定向到settings.LOGIN_URL,并将当前访问的绝对路径传递到查询字符串中。例如:/accounts/login/?next=/polls/3/。LOGIN_URL默认为/accounts/login

2如果用户已经登入,则正常执行视图。视图的代码可以安全地假设用户已经登入。

我们来进行测试下,首先没有用户登录。这个”打开目录”链接的处理函数就是被login_required装饰的preview函数

Django会话,用户和注册之用户认证

登录后页面跳转到/accounts/login/?next=/preview/。并且网页提示/accounts/login/找不到

Django会话,用户和注册之用户认证

原因在于login_required模式是重定向到/accounts/login/?next=/polls/3/的路径。如果我们想改变这个路径有两个方法:
1 在settings.py中添加我们需要的URL地址,例如LOGIN_URL = '/show_login/'
2 在装饰器中添加login_url路径
@login_required(login_url='/show_login/')
def preview(request):
    return render(request,'content.html')
添加后可以看到就跳转到我们自己自定义的登录界面上去了

Django会话,用户和注册之用户认证

默认情况下,在成功认证后用户应该被重定向的路径存储在查询字符串的一个叫做"next"的参数中。如果对该参数你倾向使用一个不同的名字,login_required()带有一个可选的redirect_field_name参数:
@login_required(login_url='/show_login/',redirect_field_name='para')
def preview(request):
    return render(request,'content.html')


Django会话,用户和注册之用户认证

那么最后来看下如果用户已经登录的情况下的处理

Django会话,用户和注册之用户认证

点击打开目录,此时直接链接到preview,并返回具体内容

Django会话,用户和注册之用户认证

Django提供了很多的认证功能,除了登录验证,还有用户权限判断。具体的功能使用参考文档:

http://python.usyiyi.cn/documents/django_182/topics/auth/default.html#