django(权限、认证)系统——用户Login,Logout
上面两篇文章,讲述的Django的Authentication系统的核心模型对象User API和相关的使用,本文继续深入,讨论如何在Web中使用Authentication系统。
前面说了,Django的这套权限系统有三个核心,User,Permission,Group。
而在Web应用中,任何的权限系统要做的第一步就是用户识别,也就是我们常说的登陆(login)。只有正确的登陆校验,知道用户是谁了,才能够知道用户能干什么,那就是许可(Permission)需要负责解决的事情,而Group则是批量设置许可的时候的一个便利手段了。
Web请求的认证:
django有一套方法,可以在每个view方法能够接收到的request对象中增加权限验证相关的方法。要做到这一点,首先需要:
- 安装SessionMiddleware和AuthenticationMiddleware。安装方法在settings文件中对MIDDLEWARE_CLASSES变量增加上述两个Middleware类。Middleware的设计几乎在任何web框架中都有体现,只不过叫法和具体实现的手段不尽相同,例如在struts2中叫做interceptor拦截器,采用函数递归Stack的方式实现(其它框架没见过有这么干的)。设计思路都是在request进入最后的处理方法之前经过一个个前处理,在处理方法处理完之后再经过一个个后处理,前后的次序恰好相反。有点点走题,请看例子:
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()方法将这两者区分开来:
if
request.user.is_authenticated():
# 做一些事情针对验证用户.
else
:
# 做一些事情对于匿名未登录用户.
那么如何登陆一个用户呢?
需要两个函数:authenticate(username,password)和login(request,user),位于django.contrib.auth模块中;
这两个方法需要结合使用,
1.authenticate(username,password)函数需要两个参数username,password,如果校验通过则返回User对象,如果校验不通过返回None,例如:
from
django.contrib.auth
import
authenticate
user
=
authenticate(username
=
'john'
, password
=
'secret'
)
if
user
is
not
None
:
if
user.is_active:
print
"You provided a correct username and password!"
else
:
print
"Your account has been disabled!"
else
:
print
"Your username and password were incorrect."
2.login接受两个参数,第一个是request对象,第二个是user对象。login方法使用SessionMiddleware将userID存入session当中。注意,在用户还未登录的时候,也存在着匿名用户的Session,在其登陆之后,之前在匿名Session中保留的信息,都会保留下来。这两个方法要结合使用,而且必须要先调用authenticate(),因为该方法会User的一个属性上纪录该用户已经通过校验了,这个属性会被随后的login过程所使用,例如:
from
django.contrib.auth
import
authenticate, login
def
my_view(request):
username
=
request.POST[
'username'
]
password
=
request.POST[
'password'
]
user
=
authenticate(username
=
username, password
=
password)
if
user
is
not
None
:
if
user.is_active:
login(request, user)
# 跳转到成功页面.
else
:
# 返回一个无效帐户的错误
else
:
# 返回登录失败页面。
我们也可以不用authenticate()进行特定于一个用户的身份校验,直接使用和User无关的几个函数进行密码相关的校验,在Django1.4中以及新版本中提供以下方法,位于模块django.contrib.auth.hashers:
- check_password(password,encoded):第一个参数是明文密码,第二个参数是加密过的密码。如果通过校验返回True,不通过返回False;
- make_password(password[,salt,hashers]):根据给定的明文密码,salt,和Django支持的加密算法,返回一个加密的密码。如果password提供的值为None,那么该返回值将永远通不过check_password()方法。这个返回值是一个特定的约定值,目前是'!';
- is_password_usable(encoded_password):判断是否给定字符串是一个hashed密码,有机会通过check_password()函数的校验。
接下来,如何登出(log out)一个用户?
我们使用django.contrib.auth.logout函数来登出用django.contrib.auth.login函数登入的用户。
logout(requet)
函数只有一个参数,就是request。没有返回值,而且即使当前用户没有登陆也不会抛出任何异常。
例子:
from
django.contrib.auth
import
logout
def
logout_view(request):
logout(request)
# 重定向到成功登出界面
这个方法,会将存储在用户session的数据全部清空,这样避免有人用当前用户的浏览器登陆然后就可以查看当前用户的数据了,回想一下login会保留anonymous用户的session数据。如果需要将一些东西加入到登出之后的用户session,那么需要在logout方法调用之后再进行。
接下来介绍Login和Logout的两个signals
Django的signal体系是一套简单实用的事件定义、事件产生、事件监听、事件处理框架,具体可以参看Django关于signal的文档。在登陆和登出这两个重要的点上,提供了两个signal:
- django.contrib.auth.signals.user_logged_in
- django.contrib.auth.signals.user_logged_out
有三个参数会随singal传过来:
- sender:user的class,如果是logout事件该值有可能是None如果用户根本就没有验证通过。
- request:HttpRequest对象
- user:user对象,如果是logout事件该值有可能是None如果用户根本就没有验证通过。
一个经常性的简单需求就是控制某些view(struts中叫做action方法)只对登陆用户开放,如果未登录用户请求该view则跳转到登录界面让其登陆。要做到这一点,我们可以这样做:
from
django.http
import
HttpResponseRedirect
def
my_view(request):
if
not
request.user.is_authenticated():
return
HttpResponseRedirect(
'/login/?next=%s'
%
request.path)
# ...
也可以这样做,返回一个错误的页面:
def
my_view(request):
if
not
request.user.is_authenticated():
return
render_to_response(
'myapp/login_error.html'
)
# ...
更为优雅的方式是用decorator:
django.contrib.auth.decorators.login_required([redirect_field_name=REDIRECT_FIELD_NAME,login_url=None])
login_required()装饰器函数做了以下事情:
- 如果当前用户没有登陆,跳转到settings.LOGIN_URL,并传递当前的绝对路径到URL请求参数中,例如:/accounts/login/?next=/polls/3/
- 如果当前用户已经登陆了,执行view方法。在view中的方法可以认为当前用户已经登陆了。
login_required方法接受两个参数:
- redirect_field_name:默认值是next。用来定义登陆成功之后的跳回之前访问界面的url。
- login_url:默认值是settings.LOGIN_URL。用来指定登陆界面的url。如果不传入改参数,就需要确保settings.LOGIN_URL的值是正确设置的。
没有参数的login_required装饰器使用方法:
from
django.contrib.auth.decorators
import
login_required
@login_required
def
my_view(request):
...
传递参数的方法:
from
django.contrib.auth.decorators
import
login_required
@login_required
(redirect_field_name
=
'my_redirect_field'
)
def
my_view(request):
...
from
django.contrib.auth.decorators
import
login_required
@login_required
(login_url
=
'/accounts/login/'
)
def
my_view(request):
...
以上就是Django提供的用于完成login和logout相关的一些API支持,使用他们可以很好的对用户进行认证了,也就是说用户是谁系统已经搞清楚了,接下来就是更细粒度的判断,判断此人究竟能做些什么,也就是Permission许可的使用了。请看 Django中的权限控制-authentication-内置版本-4。
django(权限、认证)系统——用户Login,Logout的更多相关文章
- Django之认证系统
Django之认证系统 cookie和session 1.cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞 ...
- Django的认证系统—auth模块
Django的认证系统 auth模块的知识点总结: 1. 创建超级用户 python manage.py createsuperuser from django.contrib import auth ...
- Django的认证系统
Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Djang ...
- Django auth认证系统
Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Djang ...
- Django的认证系统 auth模块
Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Djang ...
- 【Django】认证系统
目录 #. auth模块 1. 认证 authenticate() 2. 登陆 login(HttpRequest, user) 3. 注销 logout(request) 4. 认证判断 is_au ...
- Django 【认证系统】auth
本篇内容 介绍Django框架提供的auth 认证系统 方法: 方法名 备注 create_user 创建用户 authenticate 登录验证 login 记录登录状态 logout 退出用户登录 ...
- python框架之Django(12)-认证系统之auth模块
我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Django作为一个完美主义者的终极框 ...
- Django 的认证系统
Django自带的用户认证 auth 模块 from django.contrib import autu django.contrib.auth 中提供了许多方法, 这里主要介绍其中三个: auth ...
随机推荐
- python 字典dict类型合并(不能错过哦)
我要的字典的键值有些是数据库中表的字段名, 但是有些却不是, 我需要把它们整合到一起, 因此有些这篇文章.(非得凑够150个字,我也是没有办法,扯一点昨天的问题吧,话说python中的session就 ...
- Django处理流程
用户通过浏览器发送请求 请求到达request中间件,中间件对request请求做预处理或者直接返回response 若未返回response,会到达urlconf路由,找到对应视图函数 视图函数做相 ...
- Android Data Binding使用笔记
说在前面:先来三个文档,官网文档:https://developer.Android.com/topic/libraries/data-binding/index.html 官网文档的汉化版:http ...
- Ubuntu下定时任务和自启动任务的部署
1.定时任务的部署,最简单的方法是执行 crontab -e 然后在下面加上世间周期配置和要执行的命令,一般情况下,可以把要执行的任务用bash脚本封装一下,格式如下所示: minute hour ...
- Java并发-线程安全性
首先了解一下多线程的概念 多线程:两段或以上的代码同时进行,多个顺序执行流. 并发和并行的区别 并发:做一下这个做一下那个. 并行:同时进行. 线程和进程的区别 进程:资源分配的基本单位,运行中的程序 ...
- php中$_FILES应用实例
允许用户从表单上传文件是非常有用的.先来看一段HTML表单代码 <html> <body> <form action="upload_file.php" ...
- 总结Array类型中常用的方法
Array类型应该是 ECMAScript 中最常用的类型之一了,并且它定义的数组与其他语言有着相当大的区别.数组是数据的有序集合,我们可以通过下标对指定位置的数据进行读 写:特别的是,在 ECMAS ...
- shiro 权限管理配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- day07
放完了愚人节的假期后就忘记更新了,这样不好,学习的态度也有点懒散了,需要调整过来,这几天在做一个退款流程,想好了建表.逻辑设计和需求分析,然后就是写具体的代码了,有些东西还是要多学习,不然书到用时方恨 ...
- spring 整合 shiro框架
shiro是用来干嘛的?从它的官网上(http://shiro.apache.org/)基本可以了解到,她主要提供以下功能: (1)Authentication(认证) (2)Authorizatio ...