上面两篇文章,讲述的Django的Authentication系统的核心模型对象User API和相关的使用,本文继续深入,讨论如何在Web中使用Authentication系统。
前面说了,Django的这套权限系统有三个核心,User,Permission,Group。
而在Web应用中,任何的权限系统要做的第一步就是用户识别,也就是我们常说的登陆(login)。只有正确的登陆校验,知道用户是谁了,才能够知道用户能干什么,那就是许可(Permission)需要负责解决的事情,而Group则是批量设置许可的时候的一个便利手段了。
django有一套方法,可以在每个view方法能够接收到的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:
我们使用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方法调用之后再进行。
Django的signal体系是一套简单实用的事件定义、事件产生、事件监听、事件处理框架,具体可以参看Django关于signal的文档。在登陆和登出这两个重要的点上,提供了两个signal:
有三个参数会随singal传过来:
一个经常性的简单需求就是控制某些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()装饰器函数做了以下事情:
login_required方法接受两个参数:
没有参数的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。