14:django 用户认证系统
django认证系统包含三个部分:用户、权限和分组
安装
django项目默认启用了认证系统,如果不是使用django-admin.py创建项目的可以通过在settings配置文件里面的INSTALLED_APPS的列表里面添加django.contrib.auth和django.contrib.contenttypes这两项然后运行manage.py syncdb命令创建对应的数据库表即可
用户Users
在Django-1.4.10\django\contrib\auth这个目录下有一个model文件,里面有Permission,GroupManager,Group,UserManager,User,AnonymousUser这些类的源码,建议自己都去看一下,很多注释,属性名和方法名都通俗易懂,这里只点一下关键点
groups和user_permissions是是多对多的属性,分别对应到了类Group和Permission
is_active这个属性提醒我们不要轻易的删掉一些对象,我们可以设置一个标志位标识该对象是否可用
set_unusable_password,标识该用户没有密码设置,注意不等同与空密码
基本的用法
创建用户
>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
>>> user.save()
修改密码,注意是使用set_password而不是password属性
>>> from django.contrib.auth.models import User
>>> u = User.objects.get(username__exact='john')
>>> u.set_password('new password')
>>> u.save()
创建超级用户
manage.py createsuperuser --username=joe --email=joe@example.com
存储用户的额外信息
这是一个比较麻烦的事情,不过django还是提供了一个定制的方法
首先你要定义一个模型,在这个模型里面你可以定制额外的属性或者方法,然后记得添加一个名为user的一对一的属性名
from django.contrib.auth.models import User class UserProfile(models.Model):
# 必选
user = models.OneToOneField(User) # 自定义的属性或者方法
accepted_eula = models.BooleanField()
favorite_animal = models.CharField(max_length=20, default="Dragons.")
为了表明这个模型是对于那个给定的站点,我们还需要配置一个AUTH_PROFILE_MODULE,这是一个字符串,包含两部分信息,由点号相连
- app名:大小写敏感,一般是你使用manage.py startapp创建时用的名称
- 你自定义的模型名称,大小写不敏感
比如,app名为accounts,模型名为UserProfile
AUTH_PROFILE_MODULE = 'accounts.UserProfile'
一旦一个用户档案模型(额外信息模型)被定义然后用上述方法指明,每一个user对象都会有一个方法--get_profile()--去返回跟该用户相关的额外信息
然而,你必须注册一个到django.db.models.signals.post_save信号的处理程序,并且在处理程序里面,如果created为真,才创建关联的用户额外信息
# in models.py from django.contrib.auth.models import User
from django.db.models.signals import post_save # definition of UserProfile from above
# ... def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance) post_save.connect(create_user_profile, sender=User)
把UserProfile添加到admin
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User from my_user_profile_app.models import UserProfile # Define an inline admin descriptor for UserProfile model
# which acts a bit like a singleton
class UserProfileInline(admin.StackedInline):
model = UserProfile
can_delete = False
verbose_name_plural = 'profile' # Define a new User admin
class UserAdmin(UserAdmin):
inlines = (UserProfileInline, ) # Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
匿名用户
我们来看一下匿名用户的属性,是对用户的一个补充
class AnonymousUser(object):
id = None
username = ''
is_staff = False
is_active = False
is_superuser = False
_groups = EmptyManager()
_user_permissions = EmptyManager()
web请求中的认证
前面我们只是谈到了操纵认证相关对象的底层的APIs,在更高的层次,django可以把认证框架钩进请求对象request系统中
首先,安装会话中间件和认证中间件(在MIDDLEWARE_CLASSES)里面添加SessionMiddleware和AuthenticationMiddleware,安装好这两个中间件后,你可以在视图函数里面是用request.user(代表当前已经登陆的user对象,如果用户还没等,将代表一个匿名对象),可以使用is_authencated()方法来辨别是否已经登陆
如何登陆用户
django提供了两个函数django.contrib.auth:authenticate()和login()
authentecate()
用给定的用户名和密码去认证,返回一个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."
login()
在视图函数中可以使用login()方法去登陆一个用户,这个方法需要一个HttpRequest对象和一个User对象,login()函数把用户ID存在session里面(是用django的session框架,所以请确保启用了会话中间件),如果是手工登陆用户,请先条用authenticate()方法
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)
# Redirect to a success page.
else:
# Return a 'disabled account' error message
else:
# Return an 'invalid login' error message.
如何注销用户
logout()
去注销一个使用django.contrib.auth.login()方法登陆的用户,请使用在视图函数中使用django.contrib.auth.logout()方法注销,该方法需要一个HttpRequest对象并且没有返回值
from django.contrib.auth import logout def logout_view(request):
logout(request)
# Redirect to a success page.
限制登陆用户的访问
原始方法
在视图函数中检查request.user.is_authencated()是否为真,从而决定是重定向到一个登陆页面或者是错误页面
login_required装饰器
decorators.login_required([redirect_field_name=REDIRECT_FIELD_NAME, login_url=None])
作为一个快捷方式,可以直接使用login_required()装饰器
from django.contrib.auth.decorators import login_required @login_required
def my_view(request):
这个装饰器按照以下步骤:
- 如果用户没有登陆,重定向到settings.LOGIN_URL(把在查询字符串中的当前绝对路径传参过去,例如/accounts/login/?next=/polls/3/
- 如果用户已经登陆,正常执行视图函数
默认情况下,用户在成功认证后的重定向路径被存在查询字符串中的next参数中,如果你想修改的话,请使用redirect_field_name参数@login_required(redirect_field_name='my_redirect_field')
注意的是,如果你提供了redirect_field_name,那么你很有可能需要去自定义登陆模板,你可以是用login_url参数@login_required(login_url='/accounts/login/')
内建视图函数
除了上面提到的login和logout,还有以下内建的视图函数
logout_then_login(request[, login_url]):注销一个用户然后重定向到一个登陆页面
password_change(request[, template_name, post_change_redirect, password_change_form]):允许用户修改他们的密码
password_change_done(request[, template_name]):用户修改密码后的页面
password_reset(request[, is_admin_site, template_name, email_template_name,password_reset_form, token_generator, post_reset_redirect, from_email]):通过生成的一个一次性的用来重置密码的发往他们注册邮箱的链接来允许用户重置他们的密码
password_reset_done(request[, template_name]):重置密码后的页面
password_reset_confirm(request[, uidb36, token, template_name, token_generator,set_password_form, post_reset_redirect]):展示一个用来输入密码的表单
redirect_to_login(next[, login_url, redirect_field_name]):重定向到一个登陆页面然后在成功登陆后转向另一个url
内建表单
如果你不想使用上面的内建视图函数,但是又不想自己写那些表单,你可以是用这些内建的表单,这些内建的表单都位于django.contrib.zuth.forms里面
- class AdminPasswordChangeForm
-
A form used in the admin interface to change a user’s password.
- class AuthenticationForm
-
A form for logging a user in.
- class PasswordChangeForm¶
-
A form for allowing a user to change their password.
- class PasswordResetForm
-
A form for generating and emailing a one-time use link to reset a user’s password.
- class SetPasswordForm
-
A form that lets a user change his/her password without entering the old password.
- class UserChangeForm
-
A form used in the admin interface to change a user’s information and permissions.
- class UserCreationForm
A form for creating a new user.
限制通过测试登陆的用户的访问
有时候需要检查用户是否有某些权限,或者需要通过其他的测试等等才能访问,比如下面的代码:需要检测用户是否有投票的权限
def my_view(request):
if not request.user.has_perm('polls.can_vote'):
return HttpResponse("You can't vote in this poll.")
user_passes_test(func[, login_url=None]),你可以简单的使用user_passes_test
from django.contrib.auth.decorators import user_passes_test @user_passes_test(lambda u: u.has_perm('polls.can_vote'))
def my_view(request):
如果你仅仅是想要检测用户是否有某项权限,你可以是用更简单的permission_required装饰器,user_passes_test不会检测用户是否是匿名用户,只是检查是否能通过测试,这点是值得注意的,另外,如果用户没有通过测试,你可以定义login_url来重定向到一个登陆页面,如:
@user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/')
permission_required装饰器
permission_required([login_url=None, raise_exception=False]):检查用户是否具有特定的权限,可以自定义用户不具有要求权限是重定向到登陆页面,以及是否抛出异常等等
from django.contrib.auth.decorators import permission_required @permission_required('polls.can_vote', login_url='/loginpage/')
def my_view(request):
权限
上面说了很多关于权限的内容,下面我们看看django的权限系统吧
django自带一个简单的权限系统 ,提供了给特定用户和组用户赋予权限的方法 ,在django的admin站点被使用,同时你也可以在自己的代码中使用
默认权限
当django.contrib.auth被加入INSTALLED_APPS的时候,三项特别的权限--添加,修改和删除--已经为每个django模型创建好了,这三项权限是在你运行manage.py syncdb的时候创建的
假设你有个应用的app_label是foo,一个模型名为Bar,那么你可以这样来测试这三个权限
- add: user.has_perm('foo.add_bar')
- change: user.has_perm('foo.change_bar')
- delete: user.has_perm('foo.delete_bar')
自定义权限
如果要自定义权限的话,请使用permissions这个meta属性,例如:
class Task(models.Model):
...
class Meta:
permissions = (
("view_task", "Can see available tasks"),
("change_task_status", "Can change the status of tasks"),
("close_task", "Can remove a task by setting its status as closed"),
)
直接在程序中创建权限
from myapp.models import BlogPost
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(codename='can_publish',
name='Can Publish Posts',
content_type=content_type)
这个方法与上面的方法相比,
权限API
直接看一下permission类的源码
class Permission(models.Model):
name = models.CharField(_('name'), max_length=50)
content_type = models.ForeignKey(ContentType)
codename = models.CharField(_('codename'), max_length=100)
objects = PermissionManager()
模板中的认证数据
当你使用RequestContent的时候,当前已经登陆的用户和其权限在模板上下文中时可用的
Users
当前已经登陆的用户(不管是否匿名),数据被存在模板变量{{user}}里面(前提是RequestContext被使用)
{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
<p>Welcome, new user. Please log in.</p>
{% endif %}
Permissions
当前已经登陆的用户的权限被存在模板变量{{perms}}里面
{% if perms.foo %}
<p>You have permission to do something in the foo app.</p>
{% if perms.foo.can_vote %}
<p>You can vote!</p>
{% endif %}
{% if perms.foo.can_drive %}
<p>You can drive!</p>
{% endif %}
{% else %}
<p>You don't have permission to do anything in the foo app.</p>
{% endif %}
分组
看过了用户和权限,我们继续看分组吧
分组是最简单的归类的方法,分组之后你可以对组内的用户分配特定的权限或者其他label;当然,一个用户可以属于多个组;一个组里面的用户自动获取改分组拥有的权限
apis
我们直接看代码吧,哈哈,就只有组名和对应的权限两项
class Group(models.Model):
name = models.CharField(_('name'), max_length=80, unique=True)
permissions = models.ManyToManyField(Permission,
verbose_name=_('permissions'), blank=True) objects = GroupManager()
其他的认证源
一般django自带的认证系统已经满足了大部分情况下的需求,但如果你有新的的需求的时候,你可以是用其他的认证源
具体化认证后端
django有一个检查用户名密码的“认证后端”的列表,django会从列表的第一项开始尝试,直到找到匹配的一项或者最后一项位置,你可以是用AUTHENTICATION_BACKENS设置你的认证后端列表
自己写一个认证后端
一个认证后端是指一个实现了两个必选方法和一系列可选权限相关的方法的类:get_user(user_id)和authenticate(**credentials)(get_group_permissions(), get_all_permissions(),has_perm(), and has_module_perms()))
其中get_user(user_id)中的user_id可以是用户名,数据库ID或者其他 ,返回一个用户对象
authenticate把credentials的内容作为关键字参数 ,可能是这样
class MyBackend(object):
def authenticate(self, username=None, password=None):
# Check the username/password and return a User.
或者是这样
class MyBackend(object):
def authenticate(self, token=None):
# Check the token and return a User.
无论如何,authenticate都应该验证credentials中的内容,然后返回一个符合哪些验证条件的用户对象,或者None
这是一个后端的例子
from django.conf import settings
from django.contrib.auth.models import User, check_password class SettingsBackend(object):
"""
Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD. Use the login name, and a hash of the password. For example: ADMIN_LOGIN = 'admin'
ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de'
""" supports_inactive_user = False def authenticate(self, username=None, password=None):
login_valid = (settings.ADMIN_LOGIN == username)
pwd_valid = check_password(password, settings.ADMIN_PASSWORD)
if login_valid and pwd_valid:
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
# Create a new user. Note that we can set password
# to anything, because it won't be checked; the password
# from settings.py will.
user = User(username=username, password='get from settings.py')
user.is_staff = True
user.is_superuser = True
user.save()
return user
return None def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
- 平
14:django 用户认证系统的更多相关文章
- django用户认证系统——拓展 User 模型
Django 用户认证系统提供了一个内置的 User 对象,用于记录用户的用户名,密码等个人信息.对于 Django 内置的 User 模型, 仅包含以下一些主要的属性: username,即用户名 ...
- “Django用户认证系统”学习资料收集
首推追梦人物——Django用户认证系统 待续……
- django用户认证系统——重置密码7
当用户不小心忘记了密码时,网站需要提供让用户找回账户密码的功能.在示例项目中,我们将发送一封含有重置用户密码链接的邮件到用户注册时的邮箱,用户点击收到的链接就可以重置他的密码,下面是具体做法. 发送邮 ...
- django用户认证系统——修改密码6
再此之前我们已经完成了用户登录.注册.注销等功能,接下来让我们继续为用户提供修改密码的功能.该功能 Django 的 auth 应用也已经为我们提供,过程几乎和之前的登录功能完全一样. 编写修改密码模 ...
- django用户认证系统——拓展 User 模型2
Django 用户认证系统提供了一个内置的 User 对象,用于记录用户的用户名,密码等个人信息.对于 Django 内置的 User 模型, 仅包含以下一些主要的属性: username,即用户名 ...
- django用户认证系统——基本设置1
网站提供登录.注册等用户认证功能是一个常见的需求.因此,Django 提供了一套功能完整的.灵活的.易于拓展的用户认证系统:django.contrib.auth.在本教程中,我将向你展示 auth ...
- django用户认证系统——登录4
用户已经能够在我们的网站注册了,注册就是为了登录,接下来我们为用户提供登录功能.和注册不同的是,Django 已经为我们写好了登录功能的全部代码,我们不必像之前处理注册流程那样费劲了.只需几分钟的简单 ...
- D django 用户认证系统
django认证系统包含三个部分:用户.权限和分组 安装 django项目默认启用了认证系统,如果不是使用django-admin.py创建项目的可以通过在settings配置文件里面的INSTALL ...
- Django用户认证系统(二)Web请求中的认证
在每个Web请求中都提供一个 request.user 属性来表示当前用户.如果当前用户未登录,则该属性为AnonymousUser的一个实例,反之,则是一个User实例. 你可以通过is_authe ...
随机推荐
- BZOJ2242:[SDOI2011]计算器——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2242 https://www.luogu.org/problemnew/show/P2485 你被 ...
- 利用caffe的solverstate断点训练
你可以从系统 /tmp 文件夹获取,名字是什么 caffe.ubuntu.username.log.INFO.....之类 ====================================== ...
- bzoj 4900 [CTSC2017]密钥 模拟+乱搞
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4900 #include<cstring> #include<cmath&g ...
- javascript实现正整数分数约分
//m,n为正整数的分子和分母 function reductionTo(m, n) { var arr = []; if (!isInteger(m) || !isInteger(n)) { con ...
- js的作用域深入理解
一.什么是作用域 作用域是指对某一变量和方法具有访问权限的代码空间,Javascript的作用域只有两种:全局作用域和本地作用域,本地作用域是按照函数来区分的(即全局变量和局部变量)) 局部变量:只有 ...
- Codeforces 617E XOR and Favorite Number莫队
http://codeforces.com/contest/617/problem/E 题意:给出q个查询,每次询问区间内连续异或值为k的有几种情况. 思路:没有区间修改,而且扩展端点,减小端点在前缀 ...
- map/reduce之间的shuffle,partition,combiner过程的详解
Shuffle的本意是洗牌.混乱的意思,类似于java中的Collections.shuffle(List)方法,它会随机地打乱参数list里的元素顺序.MapReduce中的Shuffle过程.所谓 ...
- CPU上下文切换的次数和时间(context switch)
什么是CPU上下文切换? 现在linux是大多基于抢占式,CPU给每个任务一定的服务时间,当时间片轮转的时候,需要把当前状态保存下来,同时加载下一个任务,这个过程叫做上下文切换.时间片轮转的方式,使得 ...
- 【BZOJ】1229 [USACO2008 Nov]toy 玩具
[算法]三分+贪心 [题解] 数据范围小的版本:餐巾计划 这题不是使用最小费用流的下凸函数,因为这题是要满足最大流,那么这题到底在三分什么? 三分的这个函数,其实是总费用随卖出玩具量变化而变化的函数, ...
- JS之document例题讲解2
例题三.图片轮播 <body> <div style="width:1000px; height:250px; margin-top:30px"> < ...