使用Django认证(authentication)框架
Django拥有一个内置的认证(authentication)框架用来操作用户认证(authentication),会话(sessions),权限(permissions)以及用户组。
这个认证(authentication)系统包含了一些普通用户操作视图(views),例如:登录,登出,修改密码以及重置密码。
这个认证(authentication)系统还包含了以下模型(models):
User:一个包含了基础字段的用户模型(model);这个模型(model)的主要字段有:username, password, email, first_name, last_name, is_active。
Group:一个组模型(model)用来分类用户
Permission:执行特定操作的标识
这个框架还包含默认的认证(authentication)视图(views)和表单(forms),我们之后会用到。
注:请注意authentication和login中的不同点:authenticate()检查用户认证信息,如果用户是正确的则返回一个用户对象;login()将用户设置到当前的会话(session)中。
使用Django认证(authentication)视图(views)
Django在认证(authentication)框架中包含了一些开箱即用的:表单(forms)和视图(views)。
你之前创建的登录视图(view)是一个非常好的练习用来理解Django中的用户认证(authentication)过程。无论如何,你可以在大部分的案例中使用默认的Django认证(authentication)视图(views)。
Django提供以下视图(views)来处理认证(authentication):
login:操作表单(form)中的登录然后登录一个用户
logout:登出一个用户
logout_then_login:登出一个用户然后重定向这个用户到登录页面
Django提供以下视图(views)来操作密码修改:
password_change:操作一个表单(form)来修改用户密码
password_change_done:当用户成功修改他的密码后提供一个成功提示页面
Django还包含了以下视图(views)允许用户重置他们的密码:
password_reset:允许用户重置他的密码。它会生成一条带有一个token的一次性使用链接然后发送到用户的邮箱中。
password_reset_done:告知用户已经发送了一封可以用来重置密码的邮件到他的邮箱中。
password_reset_complete:当用户重置完成他的密码后提供一个成功提示页面。
在你的account应用中的template目录下创建一个新的目录命名为registration。这个路径是Django认证(authentication)视图(view)期望你的认证(authentication)模块(template)默认的存放路径。
用户登录
<div>
<form action={% url "login" %} method="post">
{{ form.as_p }}
{% csrf_token %}
<input type="hidden" name="next" value="{{ next }}"/>
<p><input type="submit" value="登录"></p>
</form>
</div>
Django默认使用位于django.contrib.auth.forms中的AuthenticationForm。这个表单(form)会尝试对用户进行认证,如果登录不成功就会抛出一个验证错误。如果提供了错误的认证信息,我们可以在模板(template)中使用{% if form.errors %}来找到错误。
注意:
(1).我们添加了一个隐藏的HTML元素来提交叫做next的变量值。当你在请求(request)中传递一个next参数(举个例子:http://127.0.0.1:8000/account/login/?next=/account/),这个变量是登录视图(view)首个设置的参数。next参数必须是一个URL。当这个参数被给予的时候,Django登录视图(view)将会在用户登录完成后重定向到给予的URL。
(2).在我们的地址配置中所包含的logtou_then_login视图(view)不需要任何模板(template),因为它执行了一个重定向到登录视图(view)。
(3).login_required装饰器(decorator)会检查当前用户是否通过认证,如果用户没有通过认证,它会把用户重定向到带有一个名为next的GET参数的登录URL,该GET参数保存的变量为用户当前尝试访问的页面URL。
from django.core.urlresolvers import reverse_lazy
LOGIN_REDIRECT_URL = reverse_lazy('dashboard')
LOGIN_URL = reverse_lazy('login')
LOGOUT_URL = reverse_lazy('logout')
这些设置的意义:
LOGIN_REDIRECT_URL:告诉Django用户登录成功后如果contrib.auth.views.login视图(view)没有获取到next参数将会默认重定向到哪个URL。
LOGIN_URL:重定向用户登录的URL(例如:使用login_required装饰器(decorator))。
LOGOUT_URL:重定向用户登出的URL。
我们使用reverse_lazy()来通过它们的名字动态构建URL。reverse_lazy()方法就像reverse()所做的一样reverses URLs,但是你可以通过使用这种方式在你项目的URL配置被读取之前进行reverse URLs。
通过认证(authentication)中间件当前的用户被设置在HTTP请求(request)对象中。你可以通过使用request.user访问用户信息。你会发现一个用户对象在请求(request)中,即便这个用户并没有认证通过。一个未认证的用户在请求(request)中被设置成一个AnonymousUser的实例。一个最好的方法来检查当前的用户是否通过认证是通过调用request.user.is_authenticated()。
如果在你的登出页面中看到了Django管理站点的登出页面,检查项目settings.py中的INSTALLED_APPS,确保django.contrib.admin在account应用的后面
修改密码视图(views)
password_change视图(view)将会操作表单(form)进行修改密码,当用户成功的修改他的密码后password_change_done将会显示一条成功信息。
password_reset_email.html(渲染发送给用户的重置密码邮件)
Someone asked for password reset for email {{ email }}. Follow the link below:
{{ protocol }}://{{ domain }}{% url "password_reset_confirm" uidb64=uid token=token %}
Your username, in case you've forgotten: {{ user.get_username }}
再创建另一个模板(template)password_reset_confirm.html,为它添加如下代码:
{% block content %}
Reset your password
{% if validlink %}
Please enter your new password twice:
{{ form.as_p }}
{% csrf_token %}
<input type="submit" value="修改密码">
{% else %}
The password reset link was invalid, possibly because it has already been used. Please request a new password reset.
{% endif %}
{% endblock %}
在以上模板中,我们将会检查重置链接是否有效。Django重置密码视图(view)会设置这个变量然后将它带入这个模板(template)的上下文环境中。如果重置链接有效,我们展示用户密码重置表单(form)。
用户注册
Django还提供一个UserCreationForm表单(form)给你使用,它位于django.contrib.auth.forms非常类似与我们刚才创建的表单(form)。
编辑他们的pfofile:
user_form = UserEditForm(instance=request.user,data=request.POST)
使用一个定制User模型(model)
Django还提供一个方法可以使用你自己定制的模型(model)来替代整个User模型(model)。你自己的用户类需要继承Django的AbstractUser类,这个类提供了一个抽象的模型(model)用来完整执行默认用户
使用messages框架
当处理用户的操作时,你可能想要通知你的用户关于他们操作的结果。Django有一个内置的messages框架允许你给你的用户显示一次性的提示。
messages框架提供了一个简单的方法添加消息给用户。消息被存储在数据库中并且会在用户的下一次请求中展示。你可以在你的视图(views)中导入messages模块来使用消息messages框架,用简单的快捷方式添加新的messages
from django.contrib import messages
messages.error(request, 'Something went wrong')
你可以使用add_message()方法创建新的messages或用以下任意一个快捷方法:
success():当操作成功后显示成功的messages
info():展示messages
warning():某些还没有达到失败的程度但已经包含有失败的风险,警报用
error():操作没有成功或者某些事情失败
debug():在生产环境中这种messages会移除或者忽略
创建一个定制的认证(authentication)后台
Django允许你通过不同的来源进行认证(authentication)。AUTHENTICATION_BACKENDS设置包含了所有的给你的项目的认证(authentication)后台。
1.('django.contrib.auth.backends.ModelBackend',)---默认的ModelBackend通过数据库使用django.contrib.auth中的User模型(model)来认证(authentication)用户。
2.当你使用django.contrib.auth的authenticate()函数,Django会通过每一个定义在AUTHENTICATION_BACKENDS中的后台一个接一个地尝试认证(authentication)用户,直到其中有一个后台成功的认证该用户才会停止进行认证。只有所有的后台都无法进行用户认证(authentication),他或她才不会在你的站点中通过认证(authentication)。
Django提供了一个简单的方法来定义你自己的认证(authentication)后台。一个认证(authentication)后台就是提供了如下两种方法的一个类:
authenticate():将用户信息当成参数,如果用户成功的认证(authentication)就需要返回True,反之,需要返回False。
get_user():将用户的ID当成参数然后需要返回一个用户对象
创建一个定制认证(authentication)后台非常容易,就是编写一个Python类实现上面两个方法。我们要创建一个认证(authentication)后台让用户在我们的站点中使用他们e-mail替代他们的用户名来进行认证(authentication)。
class EmailAuthBackend(object):
def authenticate(self, username=None, password=None):
try:
user = User.objects.get(email=username)
if user.check_password(password):
return user
return None
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
authenticate():我们尝试通过给予的e-mail地址获取一个用户和使用User模型(model)中内置的check_password()方法来检查密码。这个方法会对给予密码进行哈希化来和数据库中存储的加密密码进行匹配。
get_user():我们通过user_id参数获取一个用户。Django使用这个后台来认证用户之后取回User对象放置到持续的用户会话中。