Django默认提供了自己的身份认证系统,默认配置下提供有封装好的简单的用户类型以供开发人员直接使用
User类型是封装在django.contrib.auth.models模块下的一个内建类型,是身份认证的核心类型之一,其主要属性如下:
内建用户直接通过类型进行创建用户的操作,如下:
from django.contrib.auth.models import User
user = User.objects.create_user(‘account’, ‘account@email.com’, ‘password’)
user.save()
Django的身份认证系统同样包含了后台管理员身份的操作,创建后台管理员账号如下
python manage.py createsuperuser --username=john --email=joe@email.com
和常规对象的操作一致,查询并且更改用户密码,通过Django内建方法进行操作
from django.contrib.auth.models import User
user = User.objects.get(username=’account’)
user.set_password(‘new_password’)
user.save()
当然如果你已经有了后台管理员用户的话,同样可以在登录后台管理系统之后再管理界面中直接进行修改。
authenticate(request=None, **credentials) 使用authenticate()函数进行用户身份信息的验证操作,默认情况下通过关键字参数username和password进行后台认证操作,如果认证通过的情况下会返回一个认证通过的用户对象,否则返回None
from django.contrib.auth import authenticate
user = authenticate(username=’account’, password=’123123’)
if user is not None:
# 认证通过
else:
# 认证未通过
Django为web应用的权限控制提供了一套内建的权限管理系统,可以很方便的进行用户或者用户组权限的管理和认证操作
可以通过后台管理系统直接进行操作,同样的,开发人员可以通过编码的方式进行处理。 类似于Django后台系统中定义的权限访问方式如下:
权限的设置不仅仅可以指定在类型上,同样也可以直接指定到某个对象上进行操作,通过内建的操作函数has_add_permission()、has_change_permission()以及前面提到过的has_delete_permission()进行操作,他们同样可以指定给相同类型的不同对象上。
内建用户对象有两个多对多的字段,分别是group和user_permission,内建用户对象可以通过内建方法很方便的进行用户组的操作和权限的操作
# 用户组操作
myuser.groups.set([group_list])
myuser.groups.add(group1, group2..)
myuser.groups.remove(group1, group2..)
myuser.groups.clear()
# 权限的操作
myuser.user_permission.set([permission_list])
myuser.user_permission.add(perm1, perm2..)
myuser.user_permission.remove(perm1, perm2..)
myuser.user_permission.clear()
当django.contrib.auth出现在你项目配置文件的INSTALLED_APPS列表中时,系统就会默认附带三个权限[add/change/delete]的操作了,可以在你安装的每个子模块应用中使用这些权限。
默认情况下,当我们在项目中执行数据库操作migrate时,添加在INSTALLED_APPS列表中的权限认证模块django.contrib.auth需要的数据都会被执行到数据库中,并添加对应的默认权限操作。
此时如果我们有一个应用并在应用foo中有一个数据模型Bar,使用它的默认权限如下:
假设我们在自己的模块应用blog中定义了一个类型Article,可以在程序中通过如下的方式添加一个’publish’发布的权限
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from . import models
content_type = ContentType.objects.get_for_model(models.Aritlce)
permission = Permission.objects.create(
codename=‘publish’,
name=’can publish articles’,
content_type=content_type
)
此时就是给指定的类型创建了一个权限对象,这个权限就可以通过user_permission字段添加给指定的某个用户或者用户组了。
Django的模型操作后台管理代码中对于权限的检查操作进行了缓存处理,任何对象在进行权限检查操作过程中都会针对当前检查的权限进行缓存操作,即使在中途我们针对某个权限进行了更新操作,但是执行权限检查的结果还是缓存的结果。这个问题最直接的解决方案就是如果进行了权限更新的话,为了不受缓存数据的影响,直接从数据库中重新获取用户数据即可!
from django.contrib.auth.models import User, Permission
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import get_object_or_404
from myapp.modles import Article
def user_gains_perms(request, user_id):
# 获取一个用户对象
user = get_object_or_404(User, pk=user_id)
# 检查权限:注意~此时检查权限的结果会被缓存起来
user.has_perm(‘myapp.change_article’) # False
# 获取change_article权限对象
content_type = ContentType.objects.get_for_model(Article)
permission = Permission.objects.get(
code_name=’change_article’,
content_type=content_type
)
# 添加权限给用户
user.user_permission(permission)
# 检查权限:得到缓存的结果~但是此时结果是错误的
user.has_perm(‘myapp.change_article’) # False
# 重新获取对象数据
user = get_object_or_404(User, pk=user_id)
# 检查权限,得到正确的结果
user.has_perm(‘myapp.change_article’) # True
#### 1.9. web请求认证
Django通过session对象和内建中间件组件进行请求request的认证管理操作
项目中每个请求都会附带一个request.user这样的属性数据,如果用户没有登录的情况下会自动赋值一个匿名用户[AnonymousUser],否则就返回当前登录用户,主要通过如下的方式进行操作:
if requeset.user.is_authenticated:
# 认证通过的登录用户
else:
# 认证不通过的匿名用户
如果你已经有了可以登录的用户账号,并且想通过这个账号进行系统登录操作的话,可以通过login()函数进行处理
login(request, user, backends=None) 函数主要进行用户的登录操作,需要一个请求对象requset参数和一个用户对象user参数进行操作,login()会将登录的用户信息自动记录到session中。
以下是一个验证和登录合并的案例操作:
from django.contrib.auth import authenticate, login
def my_view(request):
username = request.POST[‘username’]
password = request.POST[‘password’]
# 认证操作
user = authenticate(request, username=username, password=password)
if user is not None:
# 登录操作,自动记录数据到session
login(request, user)
else:
# 没有认证成功
可以登录系统,当然可以进行安全退出系统的操作,Django封装内建了logout()函数主要实现该功能操作
logout(request) 执行一个登出操作,将通过django.contrib.auth.login()函数添加的用户信息从系统中移除,logout()函数需要一个HttpRequest请求对象参数,无返回值。
from django.contrib.auth import logout
def logout_view(request):
logout(request)
# 重定向到下一个页面
在实际项目操作过程中,需要用户身份认证才能访问的函数的正确作法推荐两种,一种是认证失败时跳转到登录页面,但是要附带当前路径信息,方便用户登录成功以后直接跳转到正在访问的页面,另一种直接跳转错误页面即可
from django.conf import settings
from django.shortcuts import redirect
def my_view(request):
if not request.user.is_authenticated:
return redirect(‘%s?next=%s’ % (settings.LOGIN_URL, request.path))
from django.shortcuts import render
def my_view(request):
if not request.user.is_authenticated:
return render(request, ‘myapp/login_error.html’)
Django提供了内置封装的装饰器进行登录认证操作,认证失败时自动跳转到项目配置文件指向的LOGIN_URL路径
from django.contrib.decorators import login_required
@login_required
def my_view(request):
pass
或者直接可以在装饰器上指定跳转到认证页面的配置
from django.contrib.decorators import login_required
@login_required(login_url=’/blog/login/’)
def my_view(request):
pass
permission_require(perm, login_url=None, raise_exception=False) 权限认证装饰器通过快捷的权限验证操作,可以很方便的控制用户访问对应的视图处理函数的操作
from django.contrib.decorators import permission_required
@permission_required(‘blog.can_comment’)
def my_view(request):
pass
和权限检查函数has_perm()一样,可以通过<app label>.<permission.codename>的方式进行认证操作,如果用户没有对应的访问权限操作的话,会自动抛出403禁止访问的异常信息,主要是PermissionDenied权限未定义的错误导致的禁止访问!