django2官方文档阅读记录-用户身份验证(User authentication)

news/2024/5/18 4:04:09 标签: python, django, 官方文档, 权限

django自带的用户身份验证启动(djangoproject.com/en/2.2/topics/auth/default/">官方文档)

django本身自带有一套权限管理系统,通过该权限管理系统,我们可以方便快捷的控制用户的登录权限,访问权限。通过简单的配置,我们就可以使用django权限管理。

  1. 编辑setting.py文件的 INSTALLED_APPS,添加 django.contrib.auth 和 django.contrib.contenttypes
  2. 编辑setting.py文件的 MIDDLEWARE, 添加 SessionMiddleware 和 AuthenticationMiddleware
  3. 如果是通过django 的 startproject 命令创建的项目的话,上述配置会自动在setting.py中设置
  4. 执行 python manage.py migrate,django会自动创建相关的用户表以及权限表。

django_6">django用户的操作

权限管理的核心,就是用户。django通过各种对用户的操作,来实现对用户权限的控制。

用户基础信息管理

  1. 你可以通过操作model的方式,来创建用户。操作的model为
    python">from django.contrib.auth.models import User
    
  2. 通过操作model来修改密码, 同样的model,要操作的方法为
    python">user = User.objects.get(username='xxx')
    user .set_password('new password')
    user.save()
    
  3. 通过命令行的方式,创建管理员用户
    python manage.py createsuperuser --username=xxx --email=xxx@example.com
    # --username: 用户名称,必须的字段
    # --email: 用户邮箱,必须字段
    # 执行完该命令后,会提示你输入密码,输入密码之后,超级用户创建完成
    # 两个必填字段如果没有填写,命令也会提示你输入。
    
  4. 用户组
    用户组可以方便你用来管理的用户,如组内的用户,拥有这个组的权限。或者你可以针对某一个组,做针对性的编码,如定时向管理员组的组员,发送系统运行情况邮件。
    相关的组模型为
    python">django.contrib.auth.models.Group
    

用户权限管理

  1. 用户验证

    python">authenticate(request=None, **credentials)
    

    该方法是用来验证用户有效性的。比如用户名长度,用户名规则,密码长度等。
    该方法会将 setting.py 中 AUTHENTICATION_BACKENDS,注册的用户验证方法,遍历验证。
    如果通过验证,则返回一个有效的User实例,否则返回None。
    你可以自定义改参数,来实现你的自定义用户验证规则。
    该参数隐式默认为

    python">['django.contrib.auth.backends.ModelBackend']
    

    该方法中的request是HttpRequest的实例,非必须项。其他验证参数,默认是使用username,password

    python"> from django.contrib.auth import authenticate
     user = authenticate(username='xxx', password='111111')
     if user is not None:
         # 用户验证通过
     else:
         # 用户验证不通过
    
  2. 权限限制
    通过ModelAdmin提供的以下四个方法,来判断用户对数据库模型的增、删、改、查权限

    python">has_view_permission()
    has_add_permission()
    has_change_permission()
    has_delete_permission()
    
  3. 默认权限
    当你的setting.py中已经配置了 django.contrib.auth 的时候, 每当你运行migrate命令。django都会对已经安装的app里的model默认添加,增、删、改、查四项权限
    你可以通过下面四个命令来验证,你的用户是否具有对应Model的增删改查权限

    python"># 验证 xxx 用户 对 app_name下面的modelname 的增删改查权限
    user = User.objects.get(username='xxx')
    user.has_perm('app_name.add_modelname')
    user.has_perm('foo.change_modelname')
    user.has_perm('foo.delete_modelname')
    user.has_perm('foo.view_modelname')
    
  4. 通过代码创建权限
    比如你想给你的房子模型,创建一个能否进入的权限

    python">from myapp.models import MyHouse
    from django.contrib.auth.models import Permission
    from django.contrib.contenttypes.models import ContentType
    
    content_type = ContentType.objects.get_for_model(MyHouse)
    permission = Permission.objects.create(
        codename='can_accsess',
        name='Can Access in my house',
        content_type=content_type,
    )
    

    如果你想给代理模型添加权限的话,在获取content_type时,要加上 for_concrete_model=false参数

    python">content_type = ContentType.objects.get_for_model(MyHouseProxy, for_concrete_model=False)
    
  5. 权限缓存
    权限刚刚被设置的时候,是不会更新到当前的用户实例的。比如:

    python">from django.contrib.auth.models import Permission, User
    from django.contrib.contenttypes.models import ContentType
    from django.shortcuts import get_object_or_404
    
    from myapp.models import MyHouse
    
    user = get_object_or_404(User, pk=1)
    content_type = ContentType.objects.get_for_model(MyHouse)
    permission = Permission.objects.get(
        codename='can_accesshouse',
        content_type=content_type,
    )
    user.user_permissions.add(permission)
    user.has_perm('myapp.can_accesshouse')
    # 这个结果就是false
    # 也就是,你信添加的用户权限,不会立即刷新到你当前的user实例里面
    # 如果你想要立即使用你的权限,你需要重新获取你的user实例
    
    user = get_object_or_404(User, pk=1)
    user.has_perm('myapp.can_accesshouse')
    # 这时的结果就是true
    
  6. 代理模型权限
    代理类的权限的使用方式和原类的使用方式是一致的,但是代理类不会继承父类的权限

    python">class Person(models.Model):
        class Meta:
            permissions = [('can_eat_pizzas', 'Can eat pizzas')]
    
    class Student(Person):
        class Meta:
            proxy = True
            permissions = [('can_deliver_pizzas', 'Can deliver pizzas')]
    
    content_type = ContentType.objects.get_for_model(Student, for_concrete_model=False)
    # 获取权限列表
    student_permissions = Permission.objects.filter(content_type=content_type)
    print([p.codename for p in student_permissions])
    # ['add_student', 'change_student', 'delete_student', 'view_student','can_deliver_pizzas']
    for permission in student_permissions:
        user.user_permissions.add(permission)
    user.has_perm('app.add_person') # false why???????
    user.has_perm('app.can_eat_pizzas') # false why???????
    user.has_perms(('app.add_student', 'app.can_deliver_pizzas')) # true why??????
    
  7. 登录管理
    django的每个request请求中,都包含有一个 request.user 用来记录当前用户的状态。如果用户是登录状态,则request.user是User的一个实例,否则它将是AnonymousUser(匿名用户)的实例。
    你可以通过request.user的is_authenticated属性,来判断用户是已登录用户还是匿名用户

    python">if request.user.is_authenticated:
        # 已登录用户
    else:
        # 匿名用户
    

    你可以通过,上面讲到的authenticate来验证用户,并将用户登录

    python">from django.contrib.auth import authenticate, login
    from django.contrib.auth import logout
    
    def my_view(request):
     username = request.POST['username']
     password = request.POST['password']
     # 默认使用用户名和密码进行验证
     # 你也可以自定义验证规则,自定义方式在上文中有
     user = authenticate(request, username=username, password=password)
     if user is not None:
         # Django的登录操作,可以阅读源码,了解其运行原理
         # login将会把用户信息保存到session中
         login(request, user)
         # 登录成功
     else:
         # 登录失败
    def logout_view(request):
        logout(request)
     # 嗨,baby你退出了
     # 该操作会清空当前用户在session中的信息,如果你的用户并没有登录。
     # 该操作也不会报异常
    

    django已经将登录操作封装好了,我们可以在自己的视图(views)的前面,通过装饰器的方式使用。
    login_required,是可以佩戴参数的,两个参数都是可选参数。

    redirect_field_name: 验证失败后,通过GET方式,传递给login_url的参数字段,默认为next
    login_url: 验证失败后,跳转的登录地址,默认取setting.py中的LOGIN_URL配置

    python">from django.contrib.auth.decorators import login_required
    
    # 如下设置,如果登录验证失败,则跳转到 登录URL为: /xxx/login?new_field=url_path
    @login_required(redirect_field_name='new_field',login_url='/xxx/login/')
    def my_view(request):
         # do what you want
    

    你也可以通过另一种方式达到login_require的方式

    python">from django.contrib.auth.mixins import LoginRequiredMixin
    
    class MyView(LoginRequiredMixin, View):
       login_url = '/xxx/login/'
       redirect_field_name = 'new_field'
    

    这两种方式,都不会限制用户的is_active属性,但是默认的AUTHENTICATION_BACKENDS验证,会将is_active=false的用户过滤掉。

  8. 用户验证
    用户验证,是我们常用的一种用户信息验证方式。在进行密码验证之前,我们首先会对用户的用户名,如长度,规则等进行验证,如果验证失败,则不会进行密码验证。通过user_passes_test我们可以实现用户验证。

    python">from django.contrib.auth.decorators import user_passes_test
    
    def email_check(user):
        return user.email.endswith('@xxx.com')
    
    # user_passes_test的第一个参数为必要参数
    # 该参数为一个返回值为User的函数
    # 以及两个可选参数:redirect_field_name和login_url、
    # user_passes_test的返回值未true/false。如果验证通过,返回true,否则返回false
    @user_passes_test(email_check)
    def my_view(request):
        # 用户验证通过了哦
    

    同样的,这种操作方式,也是有另一种实现方式的。即使用 UserPassesTestMixin

    python">from django.contrib.auth.mixins import UserPassesTestMixin
    
    class MyView(UserPassesTestMixin, View):
    
        # test_func 方法,是你必须要重写的方法。
        # django会根据test_func的内容,来对用户进行处理
        # 该方法的返回结果,必须是User的实例
        def test_func(self):
            return self.request.user.email.endswith('@example.com')
    
  9. 访问权限
    通过permission_required的装饰器,可以实现通过用户权限来限制用户是否可以访问当前的视图(views)

    python">from django.contrib.auth.decorators import permission_required
    
    # permission_required三个参数
    # 第一个参数是用户权限, 如前文所述的用户权限表达方式。 必选参数
    # 第二个参数是验证失败后,跳转的登录链接(可以是其他页面链接,如提示无权限访问)。 可选参数
    # 第三个参数是控制验证是否报异常,如果为true,则验证失败后,弹出403异常页面,并不会跳转到login_url。
    # 可选参数,默认为false
    @permission_required('polls.can_vote', login_url='/xxx/login/', raise_exception=true)
    def my_view(request):
        # 验证通过了哦
    
  10. 自定义权限验证
    permission_required,login_required,user_passes_test都是继承了AccessMixin,而实现的验证方式,你也通过继承AccessMixin,实现自定义的权限验证。

    python">from django.contrib.auth.mixins import AccessMixin
    class MyRequiredMixin(AccessMixin):
    
       # 属性 
       login_url = 'xxx'    #  get_login_url的默认返回值,如果没有,则返回setting.py 的 LOGIN_URL
       redirect_field_name = 'xxx'    # get_redirect_field_name 的默认返回值,默认值为'next'
       permission_denied_message = ‘xxx’    # get_permission_denied_message的默认返回值,默认该值为空
       raise_exception = Ture    # 是否抛出异常,默认为False。如果为True,则验证失败时,会抛出异常,不会跳转login_url
    
       # 方法
       def get_login_url(self):
           # 该方法控制,验证失败时,返回的URL
           # 默认返回 login_url,如果login_url不存在,则返回 setting.py中的 LOGIN_URL
           
       def get_permission_denied_message(self):
           # 重写该方法,可以控制,当 raise_exception为True时,抛出的异常信息。默认返回permission_denied_message的异常信息
    
       def get_redirect_field_name(self, request, *args, **kwargs):
           # 用来指定,存放用户登录成功后跳转的URL的字段。
           # 如果返回为None,则不会显示该字段
           # 默认返回redirect_field_name
    
       def handle_no_permission(self, request, *args, **kwargs):
           # 该函数的行为,取决于raise_exception ,如果raise_exception 为Ture,则抛出异常
           # 否则跳转到login_url,并且如果有redirect_field_name,login_url会带有redirect_field_name对应的参数
    
  11. 修改密码
    如果你修改了用户密码,那么你的用户session会失效。因为django会在你发送request请求的时候,验证根据你的密码生成的session。因为你的密码修改了,所以你的session就失效了。
    django本身的修改密码页面和update_session_auth_hash方法,实现了,更改密码,并且保证session不失效。其实就是在修改密码后,直接修改session对应的密码的HMAC。但是前提,你要保证你的用户模型继承了AbstractBaseUser 或者实现了get_session_auth_hash方法,django会通过该方法,获取用户密码的HMAC值。

    python">from django.contrib.auth import update_session_auth_hash
    
    def password_change(request):
       if request.method == 'POST':
           form = PasswordChangeForm(user=request.user, data=request.POST)
           if form.is_valid():
               form.save()
               update_session_auth_hash(request, form.user)
       else:
           pass
    
  12. django提供了登录,退出,密码管理的页面。你可以用现成的,也可以自己定义。

  13. 其他的权限管理页面,django提供了视图,但是没有提供模板(templates),需要你自己实现并使用


http://www.niftyadmin.cn/n/615346.html

相关文章

django错误-models.E028:::同一个表名在多个Model的db_table中使用

在meta中设置managedFalsemanaged的作用,待后续补充,源码中,会对managedtrue的model进行检测,是否有多个model使用了同一个表名。

django基础学习-权限相关整理

django权限整理 用户是权限管理的中心,django通过对用户的管理,实现了权限的控制。 group group属性类似于linux中的用户组,你可以通过给某一个组设置权限,来授权给组内所有用户,暂时还没有写代码验证具体使用方式。后…

基础环境搭建-vmtools

刚刚在虚拟机安装完成的centos7系统,下面会有提示安装vmtools,点击之后,虚拟机会自动挂载vmtools的镜像。如果没有提示,则可以在虚拟机设置->硬件设置->CD/DVD, 右侧的选择ISO镜像文件中,选中vm安装文件夹下面的…

基础环境搭建-中文输入法

1.在安装系统的时候,支持语言那里,选择支持中文,在选择简体中文,应该就会预装中文输入法 2.点击applycation->系统工具->设置->Reigon&language 3.点击输入源下面的加号 4.点击汉语 5.选择自己想要的输入法 6.然后wi…

基础环境搭建-chrome浏览器

1.chrome官网下载安装包:https://www.google.cn/intl/zh-CN/chrome/dev/ 2.使用 rpm -ivh 安装包名称,安装 3.会遇到问题: - /usr/bin/lsb_release:yum install redhat-lsb -yibXss.so.1()(64bit):yum install libXSc…

基础环境搭建-mysql数据库源码搭建

下载源码包:https://dev.mysql.com/downloads/mysql/ 官网安装教程:官网链接 groupadd mysql 创建用户组 useradd -r -g mysql -s /bin/false mysql 创建Mysql用户组下的mysql系统账号, 主要是为了系统安全 tar -xzvf mysql-VERSION.tar.gz cd mysql…

mysql8 Datetime 默认值

官网说mysql8的默认值要设置为 ‘1000-01-01’ to ‘9999-12-31’ 旧版本可以设置为 ‘0000-00-00 00:00:00’

mysql异常-not in查询结果为空

情况是这样的: 我有100个学生,我写了两个sql。 分别是: 1. 查询报名参赛的人有多少。 2. 查询没有报名参赛的人有多少。 但是两个查询结果如下: 1. 60 2. 0 这是为什么呢? 是因为,我存储报名数据时&#xf…