Django 用户登录、认证及鉴权

参考文献https://blog.csdn.net/wolaiye320/article/details/51942928  https://www.cnblogs.com/chadiandianwenrou/p/7516224.html

使用User对象

  • User实例一般从request.user,或是其他下面即将要讨论到的方法取得,它有很多属性和方法。AnonymousUser对象模拟了部分的接口,但不是全部,在把它当成真正的user对象使用前,你得检查一下user.is_authenticated()
    User对象属性
    属性描述
    username必填; 少于等于30字符. 只允许字符,数字,下划线
    first_name可选; 少于等于30字符.
    last_name可选; 少于等于30字符.
    email可选. 邮件地址.
    password必填. 密码的摘要hash(Django不会存储原始密码),详见密码章节部分
    is_staff布尔值. 用户是否拥有网站的管理权限.
    is_active布尔值. 是否允许用户登录, 设置为``False``,可以不用删除用户来禁止 用户登录
    is_superuser布尔值. 用户是否拥有所有权限,而无需任何显示的权限分配定义
    last_login用户最后登录的时间,缺省会设置为当前时间
    date_joined创建用户的时间,当用户创建时,缺省的设置为当前的时间
    User对象方法
    方法描述
    is_authenticated()如果是真正的 User对象,返回值恒为True。 用于检查用户是否已经通过了认证。通过认证并不意味着 用户拥有任何权限,甚至也不检查该用户是否处于激活状 态,这只是表明用户成功的通过了认证。
    is_anonymous()如果是个 AnonymousUser,返回值为True, 如果是 User对象,返回值为False。一般来 说,is_authenticated()会比这个方法更常用些。
    get_full_name()返回值为: first_name加上last_name,以 空格分隔。
    set_password(passwd)将用户的密码设置为给定的字符串,实际密码已被哈希 处理。这时并不会真正保存 User对象。
    check_password(passwd)如果给定的字符串通过了密码检查,返回 True。 密码比较已进行了哈希处理。
    get_group_permissions()返回用户通过所属组获得的权限列表
    get_all_permissions()返回用户通过所属组和用户自身权限所获得的所有权限 列表。
    has_perm(perm)如果用户拥有给定的权限,返回 True,perm应形如 "package.codename"的格式。如果用户处于 非激活状态,则总是返回False。
    has_perms(perm_list)如果用户拥有所有给定的权限,返回 True。 如果用户处于非激活状态,则总是返回False。
    has_module_perms(app_label)如果用户拥有任何给定 app_label的权限,返回True。如果用户处于非激活状态,则总是返回False
    get_and_delete_messages()返回用户的 Message对象列表,并从队列中删除。
    email_user(subj, msg)给用户发送电子邮件,用 DEFAULT_FROM_EMAIL的设 置作为发件人。也可以用第3个参数from_email来 覆盖设置。
    get_profile()返回用户的网站自定义profile,详见Profile章节

     

  • User对象有两个多对多的属性:groups和permissions。User对象可以象使用其他多对多属性的方法一样使用它们
    # Set a user's groups:
    myuser.groups = group_list
    # Add a user to some groups:
    myuser.groups.add(group1, group2,...)
    # Remove a user from some groups:
    myuser.groups.remove(group1, group2,...)
    # Remove a user from all groups:
    myuser.groups.clear()
    # Permissions work the same way
    myuser.permissions = permission_list
    myuser.permissions.add(permission1, permission2, ...)
    myuser.permissions.remove(permission1, permission2, ...)
    myuser.permissions.clear()

     

  • 重写User模型

    • Django内置的User模型可能不适合某些项目,我们可能要基于内置的添加一些字段,首先start一个app users用于用户管理

      django-admin startapp users

       

    • 编写users app下的models.py

      from django.db import models
      from django.contrib.auth.models import AbstractUser
      
      class UserProfile(AbstractUser):
          nick_name = models.CharField(...)
          birday = models.DateField(...)
          gender = models.CharField(...)
          address = models.CharField(...)
          mobile = models.CharField(...)
          image = models.ImageField(upload_to='image/%Y/%m', default='image/default.png', max_length=100)
      
          class Meta:
              verbose_name = "用户信息"
              verbose_name_plural = "用户信息"
      
          def __str__(self):
              return self.username

       

    • 然后修改settings.py配置文件,覆盖默认的user模型

      '''是app的名称,和models里的class名称(表名)'''
      AUTH_USER_MODEL = "users.UserProfile"

       

 

登录和登出

  •  Django 提供内置的视图(view)函数用于处理登录和退出,但在开始前,我们来看看如何手工登录和退出,Django在django.contrib.auth中提供了两个函数来处理这些事情——authenticate()和login()。

    authenticate()函数可以用于鉴定用户名和密码是否配对。它接受两个参数,用户标识(通常默认的是username)和密码password,如果密码正确会返回一个User对象;错误则返回None

    >>> from django.contrib import auth
    >>> user = auth.authenticate(username='john', password='secret')
    >>> if user is not None:
    ...     print("Correct!")
    ... else:
    ...     print("Oops, that's wrong!")

     

  • 而要登录一个用户,应该使用login(),该函数接受一个HttpRequest对象和一个User对象作为参数并使用Django的会话(session)框架把用户的ID保存在该会话中。下面的例子演示了如何在一个视图中同时使用authenticate()和login()函数

    from django.contrib import auth
    
    def login(request):
        username = request.POST['username']
        password = request.POST['password']
        user = auth.authenticate(username=username, password=password)
        if user is not None and user.is_active:
            # Correct password, and the user is marked "active"
            auth.login(request, user)
            # Redirect to a success page.
            return HttpResponseRedirect("/account/loggedin/")
        else:
            # Show an error page
            return HttpResponseRedirect("/account/invalid/")

     

  •  登出,在你的视图中使用django.contrib.auth.logout()。该函数接受一个HttpRequest对象作为参数,没有返回值。

    from django.contrib import auth
    
    def logout(request):
        auth.logout(request)
        # Redirect to a success page.
        return HttpResponseRedirect("/account/loggedout/")

    注意,即使用户没有登录,logout()也不会抛异常。

自定义登录验证

  • 如何实现通过email和用户名都能登录呢?就需要重写authenticate方法
    from django.shortcuts import render
    from django.contrib.auth import authenticate, login
    from django.contrib.auth.backends import ModelBackend
    from django.db.models import Q
    
    from .models import UserProfile
    
    
    # 重写的authenticate登录验证
    class CustomBackend(ModelBackend):
        def authenticate(self, username=None, password=None, **kwargs):
            try:
                user = UserProfile.objects.get(Q(username=username) | Q(email=username))
                # 检测username和password是否匹配
                if user.check_password(password):
                    return user
            except Exception as e:
                return None
    
    
    # 登录方法
    def acc_login(request):
        if request.method == 'POST':
            user_name = request.POST.get('username', '')
            pass_word = request.POST.get('password', '')
            user = authenticate(username=user_name, password=pass_word)    # 通过settings.py的配置,我们自定义的认证函数会被加入到一个序列中,并通过django.contrib.auth.authenticate 调用
            if user is not None:
                if user.is_active:
                    login(request, user)    # 调用django的login
                    return render(request, 'index.html')
                else:
                    return render(request, 'login.html', {'msg': '用户未激活'})
            else:
                return render(request, 'login.html', {'mgs': '用户名或密码错误'})
        elif request.method == 'GET':
            return render(request, 'login.html')

    需要注意的是,覆写的authenticate方法,应该返回一个user对象或None

  • settings.py

    AUTHENTICATION_BACKENDS = ('users.views.CustomBackend',)

    至此,就支持邮箱和用户名登录了

     

简单的权限控制

  • 限制匿名用户的访问

    • 有很多原因需要控制用户访问站点的某部分,一个简单原始的限制方法是检查request.user.is_authenticated(),然后重定向到登陆页面

      from django.http import HttpResponseRedirect
      
      def my_view(request):
          if not request.user.is_authenticated():
          return HttpResponseRedirect('/login/?next=%s' % request.path)
          # 或者显示一个出错信息:
          return render_to_response('myapp/login_error.html')

       

    • 作为一个快捷方式,你可以使用便捷的@login_required装饰器

      from django.contrib.auth.decorators import login_required
      
      @login_required
      def my_view(request):
          # @login_required做下面的事情:
          # 如果用户没有登录,重定向到登录页面,把当前绝对URL作为next在查询字符串中传递过去,例如:/accounts/login/?next=/polls/3/
          # 如果用户已经登录,正常地执行视图函数。
      

      要自动重定向到登录页面,必须在settings.py中设置LOGIN_URL

      LOGIN_URL = '/user/login/'

      当然,你也可以根据业务需要自定义装饰器

  • 限制已登录用户的访问

    • 可以通过某种权限校验,或某些特定的检查,这些实现方式大致相同。一般的方法是直接在视图函数中的request.user上运行检查。例如,下面视图检查用户登陆并是否有polls.can_vote的权限:

      def vote(request):
          if request.user.is_authenticated() and request.user.has_perm('polls.can_vote')):
              # vote here
          else:
              return HttpResponse("You can't vote in this poll.")

      但其实,django提供了一个更优雅的方式来实现以上操作

      from django.contrib.auth.decorators import user_passes_test
      
      def user_can_vote(user):
          return user.is_authenticated() and user.has_perm("polls.can_vote")
      
      @user_passes_text(user_can_vote, login_url="/login/")
      def vote(request):
          # vote here

      user_passes_test使用一个必需的参数:一个可调用的方法,它存在User对象并当此用户允许查看该页面时返回True。注意user_passes_test不会自动检查User是否认证,你应该自己做这件事。例子中我们也展示了第二个可选的参数login_url,它让你指定你的登录页面的URL(默认为settings.LOGIN_URL)。

      既然检查用户是否有一个特殊权限是相对常见的任务,Django为这种情形提供了一个捷径:@permission_required()装饰器使用这个装饰器,前面的例子可以这样写

      from django.contrib.auth.decorators import permission_required
      
      @permission_required('polls.can_vote', login_url="/login/")
      def vote(request):
          # ..

      注意,permission_required()也有一个可选的login_url参数,这个参数默认为settings.LOGIN_URL。

 

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值