2017-11-21 9 views
5

사용자가 데이터베이스를 통해 사용자 지정 쿼리를 작성할 수있는 인터페이스를 제공하려고합니다. 나는 그들이 허용 된 기록만을 조회 할 수 있도록해야한다. 이를 위해 행렬 기반 액세스 제어를 django-guardian을 사용하여 적용하기로 결정했습니다.장고의 여러 모델에 대한 원시 쿼리 및 행 수준 액세스 제어

>>> group = Group.objects.create('some group') 
>>> class_c = ClassC.objects.create('ClassC') 
>>> class_b = ClassB.objects.create('ClassB', classc=class_c) 
>>> class_a = ClassA.objects.create('ClassA', classb=class_b) 
>>> assign_perm('view_record', group, class_c) 
>>> assign_perm('view_record', group, class_b) 
>>> assign_perm('view_record', group, class_a) 
>>> get_objects_for_group(group, 'view_record') 

이 나에게 검색어 세트를 제공합니다 : 여기

내 스키마는 다음과 같이 내가 get_objects_for_group를 사용할 수 있도록하고 싶습니다

class BaseClass(models.Model): 
    somefield = models.TextField() 
    class Meta: 
     permissions = (
      ('view_record', 'View record'), 
     ) 

class ClassA(BaseClass): 
    # some other fields here 
    classb = models.ForeignKey(ClassB) 

class ClassB(BaseClass): 
    # some fields here 
    classc = models.ForeignKey(ClassC) 

class ClassC(BaseClass): 
    # some fields here 

처럼 보이는 방법이다. 위에서 정의한 BaseClass를 사용하고 다른 관련 클래스를 통해 원시 쿼리를 작성할 수 있습니까?

>>> qs.intersection(get_objects_for_group(group, 'view_record'), \ 
        BaseClass.objects.raw('select * from table_a a' 
              'join table_b b on a.id=b.table_a_id ' 
              'join table_c c on b.id=c.table_b_id ' 
              'where some conditions here')) 

이 접근 방식이 맞습니까? 이 문제를 해결할 더 좋은 방법이 있습니까?

감사합니다.

편집 : 문제는 각 사용자에 대해 별도의 테이블을 만들 수 있습니다 해결하기

또 다른 방법. 내 응용 프로그램에 추가 될 수있는 복잡성을 이해합니다. 그러나

  • 사용자 수는 오랫동안 100 초를 넘지 않습니다. 소비자 응용 프로그램이 아닙니다.
  • 우리의 사용 사례에 따라 이러한 테이블을 통해 쿼리해야 할 가능성은 거의 없습니다. 같은 모델에 속한 table1, table2, table3의 어떤 것을 집계해야하는 쿼리를 작성하지 않을 것입니다.
  • 고객 당 별도의 테이블을 유지하면 이점이 있습니다.

실용적인 접근이라고 생각하십니까?

+0

RawQuerySet에서 교차를 할 수 없다는 것을 확인했습니다. – ertan

답변

2

나는 당신이해야 할 일을 이미 알고 있다고 생각합니다. 당신이 찾고있는 단어는 멀티 테넌트입니다. 그것은 고객 당 하나의 테이블이 아니지만. 가장 적합한 것은 고객 당 하나의 스키마입니다. 불행히도, 멀티 테넌시에 대한 최고의 기사는 더 이상 제공되지 않습니다. 캐시 된 버전을 찾을 수 있는지 확인하십시오. https://msdn.microsoft.com/en-us/library/aa479086.aspx 그렇지 않으면 인터넷에 수많은 기사가 있습니다.

또 다른 가능한 접근법은 custom managers을 살펴 보는 것입니다. 각 Model-Customer에 대해 하나의 사용자 정의 관리자를 작성하고 그에 따라 조회 할 수 있습니다. 그러나이 모든 것이 애플리케이션의 복잡성을 초래할 것이며 곧 손에서 벗어날 것입니다. 애플리케이션 보안 레이어의 버그는 당신에게 악몽입니다.

무게를다는 것은 모두 당신이 편집에서 말한 것처럼 멀티 테넌시 솔루션을 말하는 것이 가장 좋은 방법입니다.

+0

필자는 PostgreSQL에서 로우 레벨 보안과 관련하여 끝날 것입니다 : https://www.postgresql.org/docs/9.5/static/ddl-rowsecurity.html. 이 기사는 응용 프로그램 수준 사용자를 포스트그레스 정책으로 연결하는 데 많은 도움을주었습니다. https://blog.2ndquadrant.com/application-users-vs-row-level-security/ – ertan

+0

흥미로운 읽기. 공유해 주셔서 감사합니다. 그러나 내가 보는 한 가지 문제가있다. 새로운 정책을 생성하고 db 계층과 응용 프로그램 계층 사이의 동시성을 유지하는 오버 헤드는 가치가 없습니다. –

+1

각 테이블에 대한 정책을 작성하는 것은 오버 헤드를 발생 시키지만 한 번만 수행하면됩니다. 스크립트를 작성하여 repo에 체크인하면 너무 나빠질 필요가 없습니다. 다시 : db 및 응용 프로그램 계층 동기화. 실제로 이것은 주로 한 줄의 코드로 세션 변수를 적절하게 설정하고 나머지는 정책 내에서 처리하여 처리합니다. 유일한 이유는 마이그레이션을 통해이 특정 필드가 변경되면 보안 결함이 발생할 수 있다는 것입니다. 일부 통합 테스트를 통해이를 완화 할 계획입니다. 멀티 테넌시와 비교하면 유지 관리가 더 간단하다고 느낍니다. – ertan

2

많은 옵션을 연구 한 결과 PostgreSQL에서 Row Level Security을 사용하여 데이터베이스 수준에서이 문제를 해결할 수 있다는 것을 알게되었습니다. 그것은 가장 쉽고 우아하게 끝납니다.

This article은 PostgreSQL 정책을 통해 응용 프로그램 수준의 사용자를 연결하는 데 많은 도움이되었습니다.나는 내 연구를 수행하여 배운 내용

입니다 : 그들은 임의의 쿼리를 실행할 수 있기 때문에 고객이 잠재적으로 서로의 쿼리 성능에 영향을 미칠 수있는 경우

  • 별도의 테이블이 여전히 미래에 옵션이 될 수 있습니다.

  • 원시 또는 임의 (ad-hoc) 쿼리를 사용하려는 경우 ORM 수준에서이를 해결하려고 시도하는 것은 거의 불가능합니다.

-1

먼저 우리가 당신을 도울 수 있도록 django와 함께 아키텍처를 설정하고 구축하는 방법에 대한 자세한 정보를 제공해야합니다. API를 구현 했습니까? django 템플릿을 사용하면 대용량 응용 프로그램을 구축하고 많은 데이터를 소비하는 경우에는 실제로 좋은 생각이 아닙니다. 이로 인해 쿼리로드가 엄청나게 영향을받을 수 있습니다. 백엔드에서 프론트 엔드를 추출 할 것을 제안 할 수 있습니다.