• Django_内置的用户认证系统


    Django内置的用户认证系统,可用于处理用户账户、群组、许可和基于cookie的用户会话。

    Django的认证系统包含了身份验证和权限管理两部分:

    • 身份验证用于核实某个用户是否合法
    • 权限管理决定一个合法用户具有哪些权限

    Django的认证系统主要包括下面几个部分:

    • 用户
    • 许可
    • 可配置的密码哈希系统
    • 用于用户登录或者限制访问的表单和视图工具
    • 可插拔的后台系统

    默认情况下,使用django-admin startproject命令后,认证相关的模块已经自动添加到settings文件内了,如果没有的话,请手动添加。

    settings.INSTALLED_APPS配置项中添加:

    • 'django.contrib.auth': 包含认证框架的核心以及默认模型
    • 'django.contrib.contenttypes':内容类型系统,用于给模型关联许可

    settings.MIDDLEWARE配置项中添加:

    • 'django.contrib.sessions.middleware.SessionMiddleware':通过请求管理会话
    • 'django.contrib.auth.middleware.AuthenticationMiddleware':将会话和用户关联

    当配置正确后,运行manage.py migrate命令,创建用户认证系统相关的数据库表以及分配预定义的权限。

    一、用户对象

    用户对象是Django认证系统的核心,在Django的认证框架中只有一个用户模型也就是User模型,它位于django.contrib.auth.models

    注意:本节内容叙述的所有功能,都是基于这个User模型的,和这个User模型没有任何关系的自定义用户模型是无法使用Django内置的认证系统功能的!

    用户模型主要有下面几个字段:

    • username
    • password
    • email
    • first_name
    • last_name

    1. 创建用户

    可使用create_user()方法创建一个新用户:

    PS D:\_git\djangodemo> python .\manage.py shell
    Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] on win32
    
    >>> from django.contrib.auth.models import User                                      
    >>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
    >>> user.last_name = 'Lennon'
    >>> user.save()

    查看auth_user表,可以看到创建的用户

    2. 修改密码

    Django默认会对密码进行加密,因此,不要在数据库中直接修改密码。

    要修改密码,有两个办法:

    • 使用命令行: python manage.py changepassword username。如果不提供用户名,则会尝试修改当前系统用户的密码。

              

    • 使用set_password()方法:
    from django.contrib.auth.models import User
    u = User.objects.get(username='john')
    u.set_password('new_password')
    u.save()

    3. 用户验证

    利用authenticate()方法,可对用户进行验证。该方法通常接收usernamepassword作为参数。要注意的是,认证的后端可能有好几个,有一项认证通过则返回一个User类对象,一项都没通过或者抛出了PermissionDenied异常,则返回一个None。例如:

    >>> from django.contrib.auth import authenticate              
    >>> user=authenticate(username='john',password='123456789')
    >>> print(user)                                              
    None
    >>> user=authenticate(username='john',password='12345678') 
    >>> print(user)                                              
    john
    >>> print(type(user))
    <class 'django.contrib.auth.models.User'>
    >>>

    二、权限与授权

    Django提供了一个简单的权限系统,并且已经用于它的admin站点,当然你也可以在你的代码中使用。

    User模型的对象有两个多对多的字段:groups和user_permissions,可以像下面这样访问他们:

    myuser.groups.set([group_list])
    myuser.groups.add(group, group, ...)
    myuser.groups.remove(group, group, ...)
    myuser.groups.clear()
    myuser.user_permissions.set([permission_list])
    myuser.user_permissions.add(permission, permission, ...)
    myuser.user_permissions.remove(permission, permission, ...)
    myuser.user_permissions.clear()

    1. 默认权限

    默认情况下,使用manage.py migrate命令时,Django会给每个已经存在的model添加默认的权限。 假设你现在有个app叫做foo,有个model叫做bar,使用下面的方式可以测试默认权限:

    add: user.has_perm('foo.add_bar')
    change: user.has_perm('foo.change_bar')
    delete: user.has_perm('foo.delete_bar')

    2. 用户组

    Django提供了一个django.contrib.auth.models.Group模型,该model可用于给用户分组,实现批量管理。用户和组属于多对多的关系。用户自动具有所属组的所有权限。

    3. 在代码中创建权限

    例如,为myapp中的BlogPost模型添加一个can_publish权限。

    from myapp.models import BlogPost
    from django.contrib.auth.models import 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,
    )

    然后,你可以通过User模型的user_permissions属性或者Group模型的permissions属性为用户添加该权限。

    4. 权限缓存

    权限检查后,会被缓存在用户对象中。参考下面的例子:

    from django.contrib.auth.models import Permission, User
    from django.shortcuts import get_object_or_404
    
    def user_gains_perms(request, user_id):
        user = get_object_or_404(User, pk=user_id)
        # any permission check will cache the current set of permissions
        user.has_perm('myapp.change_bar')
    
        permission = Permission.objects.get(codename='change_bar')
        user.user_permissions.add(permission)
    
        # Checking the cached permission set
        user.has_perm('myapp.change_bar')  # False
    
        # Request new instance of User
        # Be aware that user.refresh_from_db() won't clear the cache.
        user = get_object_or_404(User, pk=user_id)
    
        # Permission cache is repopulated from the database
        user.has_perm('myapp.change_bar')  # True
    
        ...

    三、在视图中认证用户

    Django使用session和中间件关联请求对象和认证系统。

    每一次请求中都包含一个request.user属性,表示当前用户。如果该用户未登录,该属性的值是一个AnonymousUser实例(匿名用户),如果已经登录,该属性就是一个User模型的实例。

    可以使用is_authenticated方法判断用户是否登录,如果登录则返回True,如果未登录则返回False,如下视图:

    if request.user.is_authenticated:
        # Do something for authenticated users.
        ...
    else:
        # Do something for anonymous users.
        ...

    该方法也可在模板中判定用户是否已登录。

    1、登录用户

    在视图中,使用认证系统的login()方法登录用户。它接收一个HttpRequest参数和一个User对象参数。该方法会把用户的ID保存在Django的session中。下面是一个认证和登陆的例子:

    访问结果如下:

    2、注销用户

    在视图中,使用认证系统的logout()方法注销登录的用户。它接收一个HttpRequest参数,例子如下:

    访问结果如下:

    注意,如果用户没登录,调用logout方法不会抛出错误,如果用户已登录, 调用logout后,会清空用户的session数据。

    3、用户登录的访问限制

    很多时候,我们要区分已登录用户和未登录用户,只对登录的用户开放一些页面或功能,限制未登录用户的行为。办法有很多,下面是主要几种:

    3.1、原始的办法

    如果用户未登录,重定向到登录页面,如下所示:

    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')
        # ...

    3.2、函数视图使用login_required装饰器

    方法参数说明

    login_required(redirect_field_name='next', login_url=None)

    被该装饰器装饰的视图,强制要求用户必须登录后才可以访问。

    from django.contrib.auth.decorators import login_required
    
    @login_required
    def my_view(request):
        ...

    该装饰器工作机制:

    • 如果用户未登陆,重定向到settings.LOGIN_URL,传递当前绝对路径作为url字符串的参数,例如:/accounts/login/?next=/polls/3/
    • 如果用户已经登录,执行正常的视图

    此时,默认的url中使用的参数是“next”,如果你想使用自定义的参数,请修改login_required()redirect_field_name参数,如下所示:

    from django.contrib.auth.decorators import login_required
    
    @login_required(redirect_field_name='my_redirect_field')
    def my_view(request):
        ...

    如果你这么做了,你还需要重新定制登录模板,因为它引用了redirect_field_name变量。

    login_required()装饰器还有一个可选的longin_url参数。例如:

    from django.contrib.auth.decorators import login_required
    
    @login_required(login_url='/accounts/login/')
    def my_view(request):
        ...

    注意:如果不指定login_url参数,请确保settings.LOGIN_URL已配置正确的uri,例如:

    访问被装饰视图,被重定向至LOGIN_URL路径。

    3.3、类视图继承LoginRequiredMixin

    通过继承LoginRequiredMixin类的方式限制用户。需要注意,在多继承时,该类必须为第1个父类。

    from django.contrib.auth.mixins import LoginRequiredMixin
    
    class MyView(LoginRequiredMixin, View):
        ...

    4、用户权限的访问限制

    Django内置了一个permission_required()装饰器,用于根据用户权限,决定视图的访问权限,如下所示:

    from django.contrib.auth.decorators import permission_required
    
    @permission_required('polls.can_vote')
    def my_view(request):
        ...

    权限的格式是<app label>.<permission codename>

    该装饰器还有一个可选的longin_url参数:

    from django.contrib.auth.decorators import permission_required
    
    @permission_required('polls.can_vote', login_url='/loginpage/')
    def my_view(request):
        ...

    5、认证视图

    Django为我们提供了一系列认证相关的视图,可以直接拿来用,这样你就不需要自己写登录、注销、注册等视图。但是,但是,Django没有为认证视图提供默认的模板,你需要自己写......。

    所以,除非懒癌发作,还是老老实实自己写认证相关的视图、路由和模板吧。个人认为类似跟实际生产环境结合非常紧密的视图,根本不需要这种鸡肋的内置视图,到最后,你发现还是要自己写才能满足需求。

    所以,后面的部分就不赘述了!

    原文引用:https://www.cnblogs.com/navysummer/p/10200294.html

  • 相关阅读:
    年度最佳负能量的50句话
    drbd初探及Heartbeat+DRBD+MySQL
    slatsatck file模块2种写法及系统初始化
    补鞋匠---Cobbler 服务器自动搭建
    sudo日志记录记录(rsyslog)
    [svc]lnmp一键安装脚本(含有np与mysql分离)
    webBench&ad网站并发测试工具
    Amoeba软件实现mysql读写分离
    awstat分析nginx日志
    网站的PV UV IP---网站常见软件性能
  • 原文地址:https://www.cnblogs.com/testlearn/p/16270788.html
Copyright © 2020-2023  润新知