Django-guardian을 사용하여 객체 수준의 권한 제어를 실현하는 방법

10693 단어

편집자의 경우: Django가 자체로 가지고 있는 권한 관리의 입도가 비교적 굵습니다. 만약에 한 사용자가 모델 모델에 대해 편집 (change) 권한을 가진다면 사용자는 이 모델 모델에 대응하는 모든 대상을 편집할 수 있는 권한을 가집니다.만약에 단일 대상 단계의 권한 관리를 실현하려면 반드시 제3자 패키지, 예를 들어 Django-gaurdian을 빌려야 한다.




텍스트:https://cloud.tencent.com/developer/article/1444991


개술

django-guardian은 Django에 추가 객체 기반 권한을 제공하는 인증 백엔드입니다.

특징.

  • Django의 대상이 새롭네요.
  • .
  • 익명의 사용자를 위한
  • 지원
  • 고급 API
  • 엄격한 테스트
  • Django admin의 통합
  • 장식기

    설치하다.


    Django1을 요청합니다.7 이상
    pip install django-guardian

    또는
    easy_install django-guardian

    프로비저닝


    설치가 완료되면 django-guardian을 프로젝트에 추가할 수 있습니다.우선 settings에 guardian을 INSTALLED_APPS에 넣습니다.
    INSTALLED_APPS = ( 
        # ... 
        'guardian',
    )

    인증 백엔드 AUTHENTICATION_BACKENDS에 추가
    AUTHENTICATION_BACKENDS = ( 
        'django.contrib.auth.backends.ModelBackend', #  Django 
        'guardian.backends.ObjectPermissionBackend', #  guardian 
    ) 

    주의: django-guardian을 프로젝트에 설정하면migrate 명령을 호출하면 익명 사용자의 실례 (이름 AnonymousUser) 를 만들 것입니다.guardian의 익명 사용자는 Django의 익명 사용자와 다릅니다.Django 익명 사용자는 데이터베이스에 항목이 없지만 Guardian 익명 사용자는 있습니다.이것은 다음 코드가 의외의 결과를 되돌려준다는 것을 의미한다.
    request.user.is_anonymous = True

    추가 설정


    GUARDIAN_RAISE_403

    GUARDIAN_RAISE_403True으로 설정되면guardian은 빈 django.core.exceptions.PermissionDenied으로 돌아가는 것이 아니라 django.http.HttpResponseForbidden이상을 던집니다GUARDIAN_RENDER_403GUARDIAN_RAISE_403을 동시에 True으로 설정할 수 없습니다.그렇지 않으면 django.core.exceptions.ImproperlyConfigured 이상을 던집니다

    GUARDIAN_RENDER_403

    GUARDIAN_RENDER_403True으로 설정되면 빈 django.http.HttpResponseForbidden이 아닌 403 응답이 렌더링됩니다.템플릿 파일은 GUARDIAN_TEMPLATE_403을 통해 설정됩니다.

    ANONYMOUS_USER_NAME


    익명 사용자의 사용자 이름을 설정할 수 있습니다. 기본값은 AnonymousUser입니다.

    GUARDIAN_GET_INIT_ANONYMOUS_USER


    Guardian은 익명 사용자의 대상 등급 권한을 지원하지만, 프로젝트에서 사용자 정의 사용자 모델을 사용하면 기본 기능이 실패할 수 있습니다.이것은 guardian이 매번 migrate 이후에 익명 사용자를 만들려고 시도하는 문제를 초래할 수 있습니다.이 설정이 가리키는 기능을 사용하여 만들 대상을 가져옵니다.가져오면,save 방법은 이 실례에서 호출됩니다.
    기본값은 guardian.ctypes.get_default_content_type

    GUARDIAN_GET_CONTENT_TYPE


    Guardian에서는 응용 프로그램에서 객체 및 모델에서 컨텐츠 유형을 읽어들이는 사용자 정의 함수를 제공할 수 있습니다.클래스나 클래스 차원 구조가 ContentType의 비표준 방식으로 프레임워크를 사용할 때 이것은 유용하다.대부분의 응용 프로그램에서 이 설정을 변경할 필요가 없습니다.
    예를 들어 django-polymorphic을 사용하여 모든 하위 모델의 기본 모델에 적용되는 권한을 사용할 때 유용하다.이러한 상황에서 사용자 정의 함수는 ContentType 다중모드의 기류와 ContentType 다중모드의 일반 모델을 되돌려준다.기본값은 guardian.ctypes.get_default_content_type입니다.

    예제 항목


    모델 및 사용자 정의 권한 준비


    가령 우리가 다음과 같은 모델을 가지고 있다면
    from django.db import models
    from django.contrib.auth.models import User
    # Create your models here.
    
    
    class Task(models.Model):
        summary = models.CharField(max_length=32)
        content = models.TextField()
        reported_by = models.ForeignKey(User)
        created_at = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            permissions = (
                    ('view_task', 'View task'),
                )

    설명: permissions은 사용자가 정의한 권한을 설정합니다. migrate 명령을 호출할 때 view_task은 기본 권한 집합에 추가됩니다.기본적으로 Django는 모델당 3개의 권한을 등록합니다* add모델 이름 * change모델 이름* delete모델 이름

    객체 권한 할당


    우리는 guardian.shortcuts.assign_perm() 방법을 사용하여 사용자/그룹에 대상 권한을 분배할 수 있다

    사용자에게 권한 할당

    >>> from django.contrib.auth.models import User
    >>> from todo.models import Task
    >>> from guardian.shortcuts import assign_perm
    >>> boss = User.objects.create(username="Big Boss") #  boss
    >>> joe = User.objects.create(username="joe") #  joe
    >>> task = Task.objects.create(summary="Some job", content="", reported_by=boss) #  Task 
    >>> joe.has_perm('view_task', task) #  
    False
    >>> assign_perm('view_task', joe, task) #  joe 
    
    >>> joe.has_perm('view_task', task)
    True

    사용자 그룹에 권한 할당

    >>> from django.contrib.auth.models import Group
    >>> group = Group.objects.create(name="employees")
    >>> assign_perm("change_task", group, task)
    
    >>> jack = User.objects.create(username="jack")
    >>> jack.has_perm('change_task', task)
    False
    >>> jack.groups.add(group)
    >>> jack.has_perm('change_task', task)
    True

    객체 권한 확인


    표준 방식


    이전의 예는 우리가 이미 사용했다. 우리는 사용자의 실례인 has_perm을 사용하여 어떤 권한이 있는지 검사할 수 있다.

    뷰에서 사용


    Django가 제공하는 has_perm을 제외하고 django-guardian은 우리가 대상을 검사하는 데 자주 사용하는 방법을 제공했다get_perms
    >>> from guardian.shortcuts import get_perms
    >>> 'change_task' in get_perms(joe, task)
    False
    >>> 'change_task' in get_perms(jack, task)
    True

    가급적 표준 has_perm 방법을 사용하는 것을 권장합니다.그러나 Group의 실례에 대해 그것은 쉽지 않다. get_perms은 이 문제를 해결하는 데 매우 편리하다. 왜냐하면 UserGroup의 실례를 받아들이기 때문이다.만약 우리가 더 많은 일을 해야 한다면, 우리는 ObjectPermissionChecker이라는 저급류를 사용할 수 있다. 우리는 다음 장에서 이야기할 것이다.또한 get_user_perms을 사용하여 수퍼유저 권한이나 그룹 구성원으로부터 상속받은 권한이 아닌 사용자에게 직접 권한을 할당할 수 있습니다.마찬가지로 get_group_perms은 사용자 그룹을 통한 권한만 되돌려줍니다.get_objects_for_user
    때때로 우리는 특정한 사용자, 대상의 유형과 제공된 새로운 것에 따라 대상 목록을 가져와야 한다. 예를 들어
    >>> from guardian.shortcuts import get_objects_for_user
    >>> get_objects_for_user(jack, 'todo.change_task')
    ]>
    >>> get_objects_for_user(jack, 'todo.view_task')
    
    ObjectPermissionChecker guardian.core.ObjectPermissionChecker은 특정 객체의 사용자/그룹을 검사하는 데 사용되는 권한입니다.그의 캐시 결과 때문에, 우리는 여러 번 권한을 검사한 코드의 일부분에서 사용할 수 있다
    >>> from guardian.core import ObjectPermissionChecker
    >>> cheker = ObjectPermissionChecker(joe)
    >>> checker = ObjectPermissionChecker(joe)
    >>> checker.has_perm('view_task', task)
    True
    >>> checker.has_perm('change_task', task)
    False

    장식기를 사용하다
    표준 permission_required 장식기는 검사 대상 권한을 허용하지 않습니다.django-guardian에 두 개의 장식기가 첨부되어 있습니다. 이것은 간단한 대상 권한 검사에 도움이 될 수 있지만, 장식 보기가 호출되기 전에 이 장식기들이 데이터베이스를 터치할 수 있다는 것을 기억하십시오. 이것은 보기에서 유사한 검색을 하면 가장 가능한 데이터베이스 조회가 추가로 발생할 수 있음을 의미합니다.

    템플릿에서 사용

    django-guardian에는 특정 사용자/그룹 및 인스턴스 쌍에 대한 개체 권한을 저장할 수 있는 특수 템플릿 레이블 guardian.templatetags.guardian_tags.get_obj_perms()이 포함되어 있습니다.이를 사용하려면 템플릿에 다음 항목을 배치해야 합니다.
    {% load  guardian_tags  %}
    guardian.templatetags.guardian_tags.get_obj_perms(parser, token)은 지정된 사용자 또는 그룹 및 객체(Model 인스턴스)에 대한 사용 권한 목록을 반환합니다.
    호출 형식은 다음과 같습니다.
    {% get_obj_perms user/group for obj as "context_var" %}

    예제 코드는 다음과 같습니다.
    {% get_obj_perms request.user for flatpage as "flatpage_perms" %}
    
    
    {% if "delete_flatpage" in flatpage_perms %}
        Remove page
    {% endif %}
    

    객체 권한 제거


    객체 삭제 권한은 할당만큼 간단합니다. 권한을 제거하려면 guardian.shortcuts.remove_perm()을 사용하십시오.
    >>> remove_perm("veiw_task",joe, task)
    (0, {'guardian.UserObjectPermission': 0})
    >>> joe.has_perm("view_task", task)
    True
    >>> remove_perm("view_task",joe, task)
    (1, {'guardian.UserObjectPermission': 1})
    >>> joe.has_perm("view_task", task)
    False

    고아 대상 허가


    고아 허가란 쓸데없는 허가다.대다수의 경우 별일 없을 수도 있지만 일단 발생하면 결과는 매우 심각할 수도 있다.
    Guardian은 모형 대상에 대한 사용자의 권한을 기록하는 데 사용될 때 UserObjectPermission과 GroupObjectPermission 대상을 사용합니다.그 중에서 Object에 대한 인용은 콘텐츠 type 대상(그 모델 클래스로 표시됨)과 Pk 키이고 사용자에 대한 인용은 User표의 외부 키입니다.
    예를 들면, 대상 A가 하나 있다.우리는 권한 설정을 통해 joe 사용자가 이 대상에 대해 편집 권한을 가지도록 설정합니다.어느 날 갑자기 사용자 조이가 삭제되었습니다.우리가 분배하여 만들어진 UserObjectPermission 대상은 데이터베이스에 남아 있으며, joe는 A에 대한 편집 권한이 있음을 알 수 있다.또 어느 날, 한 사용자가 사용자를 등록했습니다. 사용자username은joe입니다.이전의 기록 때문에, Joe 사용자는 A에 대한 편집 권한을 가지고 있습니다.이joe는 저joe가 아니야, 우리가 큰 실수를 했어!
    다시 예를 들어 우리가 특정한 대상을 삭제했을 때 이 대상의 특정한 권한이 이미 특정한 사용자에게 부여되면 이 권한의 기록도 효력을 상실하게 된다.삭제된 대상과 같은 모델 클래스가 언제, 메인 키가 예전과 같으면 사용자도 권한을 가지지 말아야 할 대상에게 권한을 가질 수 있다.허허, 말하기는 좀 그렇지만 이해하기 쉬울 거야.
    따라서 User와 관련된 Object를 삭제할 때, UserObjectPermission과 GroupObjectPermission 대상을 모두 삭제해야 합니다.
    이 방법을 해결하려면 세 가지 방법이 있는데 하나는 현식 인코딩이고 하나는 이를 통해 제공된 사용자 정의django 명령이다.
    $ python manage.py clean_orphan_obj_perms  
    

    또 하나는 정기적으로 구아디아를 호출하는 것이다.utils.clean_orphan_obj_perms().이 함수는 삭제된 대상의 수를 되돌려줍니다.python의 세계에서, 우리는celery를 사용하여 이 임무를 정기적으로 스케줄링할 수 있다.그러나 사용자 정의 명령과 정기 스케줄링은 합리적인 생산 환경의 해결 방법이 아니다.진정으로 해결하려면 수동 인코딩이 필요하다. 가장 우아한 방법은postUser 또는 Object 객체에 대한 예제 코드는 다음과 같습니다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    from django.contrib.auth.models import User
    from django.contrib.contenttypes.models import ContentType
    from django.db.models import Q
    from django.db.models.signals import pre_delete
    from guardian.models import UserObjectPermission
    from guardian.models import GroupObjectPermission
    from school.models import StudyGroup
     
     
    def remove_obj_perms_connected_with_user(sender, instance, **kwargs):
        filters = Q(content_type=ContentType.objects.get_for_model(instance),
            object_pk=instance.pk)
        UserObjectPermission.objects.filter(filters).delete()
        GroupObjectPermission.objects.filter(filters).delete()
     
    pre_delete.connect(remove_obj_perms_connected_with_user, sender=StudyGroup)
    

    관련 읽기
    Django 베이스(23): 권한 관리(permissions) 및 사용자 그룹(group) 상세 정보

    좋은 웹페이지 즐겨찾기