zoukankan      html  css  js  c++  java
  • Django auth

    auth是django一个自带的用户验证系统,使用它可以减少我们的开发流程。

    基本使用

    大体流程:

    1. 自定义类
      from django.contrib.auth.models import AbstractUser
      from django.db import models
      
      
      class UserInfo(she):
      	"""
      	用户信息表
      	"""
      	uid= models.AutoField(primary_key=True)
      	phone = models.CharField(max_length=11, null=True, unique=True)
      
      	def __str__(self):
      		return self.username
      
      
    2. 告知django自定义了谁
      设置settings.AUTH_USER_MODEL,格式:app名.表名
      # settings.py
       AUTH_USER_MODEL = "web.UserInfo"
      
    3. 在视图中使用auth
      from django.shortcuts import redirect
      from django.http import HttpResponse, 
      def index(request):
      	if not request.user.is_authenticated:
      		login_url = reverse("web:login")
      		return redirect(login_url + "?next=%s" % request.path)
      	return HttpResponse("<h1>index page</h1>")
      

    request.user

    如果已经登录, request.usersettings.AUTH_USER_MODEL配置中的model对象(默认为django.contrib.auth.models.User),表示当前用户。如果该用户未登陆,该属性的值是一个django.contrib.auth.models.AnonymousUser实例
    可以说,利用 request.user我们可以做一切有关于auth的东西。
    该模型的API请查看官网:User 模型

    权限

    添加默认权限

    官网:“当 INSTALLED_APPS 设置了 django.contrib.auth 时,它将确保你的每个 Django 模型被创建时有四个默认权限:添加、修改、删除和查看。”
    也就是说,django的权限是以表为单位的,下面说明如何分配权限,至于如何检验权限,请看下文场景中的访问限制
    假如是superuser的话,默认拥有全部权限。

    默认的权限格式:操作_表名(小写),如:add_testmodeldelete_testmodelchange_testmodelview_testmodel(testmodel是表名称的小写),它们分别对应增删改查。
    这些权限需要手动分配个用户或组

    user_permissions字段和group字段
    这两个是多对多关系,可以用.set([x, x])add(x, x, ...).remove(x, x, ...).clear()这四种方法

    from django.contrib.auth.models import Permission
    from django.shortcuts import render, redirect
    from django.http imprt HttpResponse
    
    from web.models import UserInfo
    
    
    def register(request):
        if request.method == "GET":
            return render(request, "web/register.html")
        elif request.method == "POST":
            # 验证数据
            # 略
    
            data = {
                "username": request.POST.get("username"),
                "email": request.POST.get("email"),
                "password": request.POST.get("pwd"),
            }
            user = UserInfo.objects.create_user(**data)
            
            # Permission是内置的权限表,django的权限都应该放在这里,具体字段看自定义权限部分
            permission = Permission.objects.get(codename="view_testmodel")		# 查看web.TestModel的权限
            
            # user_permissions是多对多关系
            user.user_permissions.add(permission)
            user.save()
    
            return redirect("web:index")
        return HttpResponse("不支持方法:%s" % request.method)
    
    

    自定义权限

    仅仅是增删改查,肯定是很多应付复杂的情况,所以django还允许我们自定义权限。

    django.contrib.auth.models.Permission表的字段:

    • name 该权限的名称,用来给用户看的
    • codename 改权限的标识,如默认的view_xx,注意是没有app的,在使用request.user.has_perm时才有,如:request.user.has_perm("web.view_testmodel")
    • content_type 外键。django.contrib.contenttypes.models.ContentType对象

    方法一:在django shell中执行:

    $ python manage.py shell
    Python 3.9.5 (tags/v3.9.5:0a7dcbd, May  3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> from web.models import TestModel
    >>> from django.contrib.contenttypes.models import ContentType
    >>> from django.contrib.auth.models import Permission
    >>> 
    >>> 
    >>> content_type = ContentType.objects.get_for_model(TestModel)
    >>> Permission.objects.create(
    ...         codename='can_reset',
    ...         name='能够重置数据',
    ...         content_type=content_type,
    ...     )
    <Permission: web | test model | 能够重置数据>
    >>>
    

    方法二:在views中定义:

    from web.models import TestModel
    from django.contrib.auth.models import Permission
    from django.contrib.contenttypes.models import ContentType
    	
    def permission_create(request):
        content_type = ContentType.objects.get_for_model(TestModel)
    
        Permission.objects.create(
            codename='can_publish',
            name='能够发布消息',
            content_type=content_type,
        )
        return HttpResponse("ok!")
    
    

    方法三:在model中定义:

    class TestModel(models.Model):
        name = models.CharField(verbose_name="测试", max_length=32)
    
        class Meta:
            permissions = [
                ("cancel_task", "取消任务"),
                ("publish_task", "发布任务"),
            ]
    
    

    注意:这种方法需要执行makemigrationsmigrate命令,这样才会把Meta中的权限添加到auth的permission表中!!!

    根据组分配权限

    使用用户进行权限管理,简直不要太麻烦了,假如要新增一个权限,我还需要给每个用户都执行一次正增加权限的命令吗?显然较为繁琐。所以最好的方式是以组为单位分配权限。
    步骤:

    1. 创建一个组
    2. 给用户分配一个组
    3. 给组分配权限

    django.contrib.auth.models.Group的字段:

    • name 组名
    • permissions 多对多字段,接收权限表
    
    def test(request):
        # 1. 创建一个组
        from django.contrib.auth.models import Group
        g = Group.objects.create(name="consumer group")
    
        # 2. 给用户分配权组
        request.user.groups.add(g)
    
        # 3. 给组分配权限
        permission = Permission.objects.get(codename="delete_testmodel")
        g.permissions.add(permission)
        return HttpResponse("ok")
    
    
    

    或者使用django shell

    
    $ python manage.py shell
    Python 3.9.5 (tags/v3.9.5:0a7dcbd, May  3 2021, 17:27:52) [MSC v.1928 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> from django.contrib.auth.models import Permission, Group
    >>> from web.models import UserInfo
    >>> 
    >>> 
    >>> user = UserInfo.objects.get(pk=1)
    >>> g = Group.objects.create(name="consumer group")
    >>> user.groups.add(g)
    >>> 
    >>> permission = Permission.objects.get(codename="delete_testmodel")
    >>> g.permissions.add(permission)
    
    

    场景

    用户管理

    1. 创建用户
      创建普通用户直接ojects管理器的create_user方法即可:
      签名:
      create_user(self, username, email=None, password=None, **extra_fields)

      
      from django.shortcuts import render, redirect
      from django.http import HttpResponse
      from web.models import UserInfo
      
      
      # Create your views here.
      
      def index(request):
      	return HttpResponse("<h1>index page</h1>")
      
      
      def register(request):
      	if request.method == "GET":
      		return render(request, "web/register.html")
      	elif request.method == "POST":
      		# 验证数据
      		# 略,假设已经验证了
      
      		data = {
      			"username": request.POST.get("username"),
      			"email": request.POST.get("email"),
      			"password": request.POST.get("pwd"),
      		}
      		user = UserInfo.objects.create_user(**data)
      
      		# create_user(self, username, email=None, password=None, **extra_fields):
      
      		# 此时此时,数据库中已经创建好了信息
      
      		# 假如要添加额外信息的话, 也可以在上面添加:
      		user.phone = request.POST.get("phone")
      		# 是否为超级用户
      		user.is_superuser = True
      		# 也可以调用UserInfo.objects.create_superuser方法,参数一样,直接直接创建超级用户
      		
      		# 是否为员工
      		user.is_staff = True
      
      		# 记得调用save !!!!!!!!!!!!!
      		user.save()
      		return redirect("web:index")
      	return HttpResponse("不支持方法:%s" % request.method)
      
    2. 修改用户信息
      根据主键直接改就行了。

    3. 修改用户密码

      def test(request):
      	if request.user.check_password("old password"):
      		request.user.set_password('new password')
      		request.user.save()
      		return HttpResponse("ok")
      	return HttpResponse("旧密码不对")
      
      
    4. 删除用户
      可以直接删除,也可把用户的活跃状态设为False,而has_perm() 等权限检查方法,以及 Django 管理中的认证方法,都会对非活跃用户返回 False。

      def test(request):
      	request.user.is_active=False
      	request.user.save()
      	return HttpResponse("ok")
      
      

    登录、注销

    1. 登录
      使用django.contrib.auth.authenticate,login登录后,会将登录信息写入session中。
      authenticate(request=None, **credentials):负责验证用户名和密码是否对应
      login(request, user, backend=None):负责将已登录的用户信息写入到session中

      from django.shortcuts import render, redirect
      from django.contrib.auth import authenticate, login
      from django.http import HttpResponse
      
      
      def login_user(request):
      	if request.method == "GET":
      		redirect_path = request.GET.get("next", reverse("web:index"))
      		return render(request, "web/login.html", {"next": redirect_path})
      	elif request.method == "POST":
      		username = request.POST['username']
      		password = request.POST['pwd']
      		# 验证
      		user = authenticate(request, username=username, password=password)
      		if user is not None:
      			# 登录,写入session信息
      			login(request, user)
      			redirect_path = request.GET.get("next", reverse("web:index"))
      			return redirect(redirect_path)
      		else:
      			return HttpResponse("账号或密码错误")
      
      
    2. 注销
      使用django.contrib.auth.logout注销用户

      假如用户未登录,logout()也不会报错

      from django.contrib.auth import logout
      from django.http import HttpResponse
      
      
      def logout_user(request):
      	logout(request)
      	return HttpResponse("已经退出登录")
      

    访问限制

    1. 判断是否登录

      1. 原始方法:
        from django.shortcuts import redirect
        from django.http import HttpResponse, 
        def index(request):
        	if not request.user.is_authenticated:
        		login_url = reverse("web:login")
        		return redirect(login_url + "?next=%s" % request.path)
        	return HttpResponse("<h1>index page</h1>")
        
      2. 使用装饰器
        需要使用:django.contrib.auth.decorators.login_required,签名:
        login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None)
        redirect_field_name默认为next
        login_url 需要指定,否则使用settings.LOGIN_URL
        from django.contrib.auth.decorators import login_required
        from django.http import HttpResponse, 
        
        
        @login_required(login_url="/web/login/")
        def index(request):
        	if not request.user.is_authenticated:
        		login_url = reverse("web:login")
        		return redirect(login_url + "?next=%s" % request.path)
        	return HttpResponse("<h1>index page</h1>")
        
        
      3. CBV使用
        利用from django.utils.decorators.method_decorator嵌套一下:
        from django.contrib.auth.decorators import login_required
        from django.utils.decorators import method_decorator
        
        
        class Home(views.View):
        
        @method_decorator(login_required)
        def get(self, request):
        return render(request, 'home.html')
        
    2. 判断是否有权限操作

      1. 原始方法:
        使用request.user.has_perm方法,参数是app名字.权限名字,返回值为布尔值。
        @login_required(login_url="/web/login/")
        def task(request):
        	if request.user.has_perm("web.publish_task"):
        		return HttpResponse("publish task ok")
        	return HttpResponse("403")
        
        
        
      2. 装饰器:
        @login_required
        @permission_required("web.publish_task", login_url="/web/login/",  raise_exception=True)
        def task(request):
        	return HttpResponse("publish task ok")
        
        
        raise_exception不为True时,会跳转到登录页面,为True时,假如没有权限,将抛出PermissionDenied异常,返回403页面,该页面可以自定制。

    本文来自博客园,作者:忞翛,转载请注明原文链接:https://www.cnblogs.com/lczmx/p/15210702.html

  • 相关阅读:
    WebBrowser.ExecWB的完整说明
    jQuery选择器的灵活用法
    Nooice, 首次开通博客园
    【HDU】3663 Power Stations
    【HDU】4069 Squiggly Sudoku
    【FOJ】2076 SUDOKU
    【HDU】3529 Bomberman Just Search!
    【HDU】3909 Sudoku
    【HDU】2780 SuSuSudoku
    【HDU】3111 Sudoku
  • 原文地址:https://www.cnblogs.com/lczmx/p/15210702.html
Copyright © 2011-2022 走看看