Django의 사용자 모듈 및 권한 시스템

10605 단어
머리말
좋은 사용자 시스템을 설계하는 것은 흔히 쉽지 않다. Django가 제공하는 사용자 시스템은 기본적인 기능을 신속하게 실현할 수 있고 이를 바탕으로 우리의 수요를 만족시키기 위해 계속 확장할 수 있다.
먼저 Django의 사용자 시스템이 제공하는 기능을 살펴보겠습니다.
  • User Model
  • 제공
  • 권한 검증(기본적으로 기존 모듈의 추가 삭제 수정 권한 추가)
  • 사용자 그룹 및 그룹 권한 기능
  • 사용자 모니터링 및 로그인 기능
  • 사용자 로그인 검증과 관련된 일부 함수와 장식 방법
  • 만약에 Django의 사용자 시스템을 설정했다면 Django가 제공하는 몇 가지 함수만 호출하면 사용자의 로그인, 로그아웃, 권한 검증 등 기능을 실현할 수 있다.예컨대 다음과 같은 상황
    1. 로그인
    # some_view.py
    from django.contrib.auth import authenticate, login
    
    def login(request):
        username = request.POST['username']
        password = request.POST['password']
    
        # Django   authenticate  ,                 
        user = authenticate(username=username, password=password)
    
        if user is not None:
            # Django   login  ,              key 
            login(request, user)
    
            #          ,       
            ...
        else:
            #             
            ...

    2. 로그아웃
    # some_view.py
    from django.contrib.auth import logout
    
    def logout(request):
        # logout                  
        logout(request)

    3. 로그인 여부 확인
    # some_view.py
    
    def some_fuction(request):
        user = request.user
        if user.is_authenticated:
            #      ,        
        else:
            #         

    4. 권한이 있는지 확인
    # some_view.py
    
    def some_fuction(request):
        user = request.user
        if user.has_perm('myapp.change_bar'):
            #    ,        
        else:
            #          

    사용자 모듈
    Django의 사용자 모듈 클래스는 auth 응용 프로그램에 정의됩니다. 예를 들어 Django의 사용자 클래스를 직접 사용하려면 setting 설정 파일의 INSTALL APP에 한 줄django.contrib.auth을 추가합니다.
    이렇게 하면 코드에서 User 클래스로 사용자를 직접 만들 수 있습니다.
    from django.contrib.auth.models import User
    user = User.objects.create_user('john', '[email protected]', 'johnpassword')
    user.last_name = 'Lennon'
    user.save()

    Django의 소스 User 클래스에 정의된 속성에 대해 살펴보십시오.
    class User(AbstractUser):
        """
        Users within the Django authentication system are represented by this
        model.
        Username, password and email are required. Other fields are optional.
        """
        class Meta(AbstractUser.Meta):
            swappable = 'AUTH_USER_MODEL'

    ..., 아무것도 없나?
    User 클래스는 AbstractUser 클래스를 계승하고 사용자 이름과 비밀번호 정보 등이 부모 클래스에 정의되어 있음을 알 수 있습니다.그래서 AbstractUser 클래스의 정의를 다시 한 번 봅시다. 편폭에 따라 그 중 일부만 열거하고 원본 코드는https://github.com/django/django/blob/master/django/contrib/auth/models.py
    class AbstractUser(AbstractBaseUser, PermissionsMixin):
        username = models.CharField(
            _('username'),
            max_length=150,
            unique=True,
            help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
            validators=[username_validator],
            error_messages={
                'unique': _("A user with that username already exists."),
            },
        )
        first_name = models.CharField(_('first name'), max_length=30, blank=True)
        last_name = models.CharField(_('last name'), max_length=30, blank=True)
        email = models.EmailField(_('email address'), blank=True)
        date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
    ....

    AbstractUser 클래스에서username이 정의된 필드를 볼 수 있으며 이메일,first 도 있습니다name、last_name 등AbstractUser 클래스는 AbstractBaseUser와PermissionsMixin 클래스를 계승하고, AbstractBaseUser 클래스는password 필드와 비밀번호를 암호화하여 저장하는 방법을 제공하며, PermissionsMixin 클래스는 User 클래스 권한 인증 기능을 제공합니다.
    전반적으로 User 클래스는 다음 필드를 정의합니다.
  • username: 사용자 이름
  • password: 비밀번호
  • first_name: 이름
  • last_name: 이름
  • email: 메일박스
  • groups: Group 클래스 다중 관계 대상 관리자
  • user_permissions: Permission 클래스 다중 관계 대상 관리자
  • is_staff: 스태프 여부
  • is_active: 활성화 여부
  • is_superuser: 관리자 여부
  • last_login: 최근 로그인 시간
  • date_joined: 등록 시간
  • 또한 다음 속성을 사용할 수 있는 User 인스턴스를 생성합니다.
  • is_authenticated: 사용자의 존재 여부를 판단하기 위해 읽기만 합니다.AnonymousUser 클래스만 False입니다.
  • is_anonymous: User와 Anonymouser 대상을 구분하는 데 쓰일 뿐입니다.

  • User 클래스는 다음과 같은 다양한 방법을 제공합니다.
  • set_password(raw password):password를hash값으로 바꿀 수 있습니다.user를 다시 호출하는 것을 기억하십시오.저장
  • check_password(raw password): 반대로 원본 암호를 데이터베이스에 저장된hash값 암호와 비교한다(직접 비교는 틀림없이 같지 않다).
  • has_perm(perm, obj=None),has_perms(perm list,obj=None): 사용자가 권한이나 권한 목록을 가지고 있는지 확인
  • get_all_permissions(obj=None): 이 사용자가 가진 모든 권한을 되돌려줍니다
  • 3 인증 및 로그인 사용자
    사용자 이름과 비밀번호를 검증하는 것은 매우 간단해 보이지만 제출한 사용자 이름과 비밀번호가 데이터베이스에 저장된 것과 일치하도록 비교하면 된다.
    예:
    # some_view.py
    def some_fuction(request):
        username = request.POST['username']
        password = request.POST['password']
        try:
            user = User.objects.get(username=username, password=password)
        except ObjectNotExists:
            #              
    
        ...

    비밀번호가 이미hash 후에 저장되었기 때문에 상술한 코드는 제출한password값을 먼저hash 다음에 데이터베이스에서 검색해야 하기 때문에 반드시 코드를 좀 더 써야 한다.이러한 Django는 가이드의 인스턴스 코드와 같이 authenticate 함수를 사용하여 사용자가 있는지 확인할 수 있습니다.
    # some_view.py
    from django.contrib.auth import authenticate, login
    
    def login(request):
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user is not None:
            login(request, user)
            ...
        else:
            ...

    여기에 authenticate와login 함수를 중점적으로 설명한다.
    1. authenticate(**credentials)
    검증할 인자를 전송합니다. 기본값은username과password입니다. 시스템 설정에 있는 모든 authentication backend 을 호출하여 검증합니다. 검증은 User 실례를 되돌려줍니다. 그렇지 않으면 None을 되돌려줍니다.
    각각 authentication backend 은 인증 백엔드를 가리키며 setting에 있습니다.py에서 구성된 AUTHENTICATIONBACKENDS 변수는 기본적으로 ['django.contrib.auth.backends.ModelBackend']로 사용자 정의 인증 백엔드를 추가하거나 제3자가 제공하는 것을 사용할 수 있습니다.authenticate 함수는 모든 인증을 순서대로 호출합니다. 첫 번째 인증이 통과되지 않으면 두 번째 인증을 사용하여 모든 인증 백엔드가 실패한 후에야 None으로 돌아갑니다.
    이 ModelBackend 클래스가 인증 사용자에게 어떻게 되돌아오는지 보십시오. (원본 코드를 다시 줄입니다.)
    class ModelBackend(object):
        def authenticate(self, request, username=None, password=None, **kwargs):
            if username is None:
                username = kwargs.get(UserModel.USERNAME_FIELD)
            try:
                user = UserModel._default_manager.get_by_natural_key(username)
            except UserModel.DoesNotExist:
    
                UserModel().set_password(password)
            else:
                if user.check_password(password) and self.user_can_authenticate(user):
                    return user
    # ...

    실제로 authenticate 함수는 모든 authentication backend 클래스의 authenticate 방법을 호출합니다.ModelBackend 클래스는 이전의 검증 방법과 약간 다르기 때문에 데이터베이스 사용자 테이블에서username에 대응하는 User 실례를 꺼내고 User의 check 를 통과합니다.password 방법은 password가 정확한지 확인하고 이 User 실례를 되돌려줍니다.
    2. login(request, user, backend=None)
    Http Request 대상과 User 대상을 받으면login 함수는 현재 사용자 정보를 세션 쿠키에 저장하기 때문에 Django 사용자 시스템의 모든 기능을 사용하려면 Django 기본 세션 앱을 설치해야 합니다.
    login 함수가 무엇을 했는지 보십시오:
    def login(request, user, backend=None):
        # (     session  )
        # ...
        request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
        request.session[BACKEND_SESSION_KEY] = backend
        request.session[HASH_SESSION_KEY] = session_auth_hash
        if hasattr(request, 'user'):
           request.user = user
        rotate_token(request)
        user_logged_in.send(sender=user.__class__, request=request, user=user)

    login 함수는 현재 사용자의 유일한 표지 정보를 Request에 저장합니다.sessionSESSION_KEY에서 다음 요청 시 세션 쿠키에서 현재 로그인한 사용자 대상을 받을 수 있습니다.
    적절한 View에 액세스하기 위해 로그인이 필요한 경우 다음과 같이 쓸 수 있습니다.
    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))

    login 함수를 통해 사용자 정보를 세션에 저장할 수 있습니다. 현재 요청이view에 도착하기 전에 Django의 세션 중간부품은 세션 쿠키에서 사용자 대상을 추출하고 Request에 값을 부여합니다.user.이렇게 하면 로그인한 사용자 Request.user.is_authenticated 값은 True이며 적절한 작업을 수행할 수 있습니다.로그인하지 않은 사용자 request.user가 is AnonymousUser 객체를 반환합니다.authenticated 속성 값은 영원히 False입니다. 이 요청을 로그인 페이지로 다시 지정해야 합니다.
    이 두 줄 코드는view 함수에 장식기를 추가하여 실현할 수 있습니다. 예를 들어
    @login_required
    def my_view(request):
        ...

    장식기login_required(redirect_field_name='next', login_url=None),login 전송 가능url 파라미터는 로그인하지 않은 사용자의 요청 방향을 바꾸는 주소를 설정합니다. 그렇지 않으면settings로 변경합니다.LOGIN_URL.
    네 가지 권한 인증
    User 모델에는 두 개의 다중 관계 필드가 있습니다:groups와userpermissions - Pemission 모델과 관련이 있습니다.User와 Pemission, User와 Permission, Group과 Permission은 모두 다대다관계이다. Permission은 구체적인 권한을 정의하고 그 필드는 다음과 같다.
    class Permission(models.Model):
        name = models.CharField(_('name'), max_length=255)      #     (    )
        content_type = models.ForeignKey(       #     :             ,        
            ContentType,
            models.CASCADE,
            verbose_name=_('content type'),
        )
        codename = models.CharField(_('codename'), max_length=100)   #        ,   has_permission    

    사용자에게 권한을 추가하고 삭제하는 것은 간단합니다: myuser.user_permissions.set([permission_list]) myuser.user_permissions.add(permission, permission, …) myuser.user_permissions.remove(permission, permission, …) myuser.user_permissions.clear()
    그 중에서 퍼미션은 구체적인 퍼미션 대상이다.사용자가 있는 그룹을 통해 그룹 권한을 추가할 수도 있습니다.permissions.set([permission_list]) group.permissions.add(permission, permission, …) group.permissions.remove(permission, permission, …) group.permissions.clear()
    이 사용자가 이 그룹에 가입하기만 하면 그룹 권한도 있습니다.User 객체의 get 을 통해all_permissions(obj=None) 방법은 이 사용자의 모든 권한 목록(문자 목록)을 얻을 수 있고 get 을 통해group_permissions(obj=None)는 해당 그룹 권한 목록을 가져옵니다.
    우리가 더 자주 해야 할 일은view에서 작업을 실행하기 전에 사용자가 지정한 권한을 가지고 있는지 확인하는 것입니다. 여기에는 User 대상의 has_perm(perm, obj=None) 방법이나 has_perms(perm_list, obj=None) 판단이 사용됩니다.has_perm(perm, obj=None) 방법 중perm은'입니다."형식의 권한 문자열. 이 권한이 있으면 방법은 True로 돌아갑니다. 마찬가지로 'has perms (perm list, obj=None)' 방법에서perm list는 '입니다."형식의 권한 문자열 목록입니다.
    동loginrequired 장식기, 권한 인증에 대응하는permissionrequired 장식기:permission_required(perm, login_url=None, raise_exception=False)
    하면, 만약, 만약...exception=True, 권한이 인증되지 않으면 PermissionDenied 이상을 던지고 기본 403페이지를 되돌려줍니다.
    Done.
    원본 주소:http://neven.me/django/2016/11/26/Django%E7%9A%84%E7%94%A8%E6%88%B7%E6%A8%A1%E5%9D%97%E4%B8%8E%E6%9D%83%E9%99%90%E7%B3%BB%E7%BB%9F/

    좋은 웹페이지 즐겨찾기