2012-04-22 2 views
6

필자는 내 웹 사이트에 Pyramid의 보안 기능을 구현하려고하지만이를 사용하는 방법을 파악하는 데 어려움을 겪고 있습니다.URL의 단일 페이지 ID를 기반으로 권한을 어떻게 제한합니까?

나는 this tutorialthis example 및 Pyramid 문서를 읽고 있으며 단일 페이지 ID에 대한 인증 정책을 구현하는 방법을 알 수 없습니다.

/pages 
/pages/12 

/pages 분명히 가능한 페이지를 나열하고 페이지/코멘트를 읽을 수있는 /pages/:id은 다음과 같습니다

예를 들어, 나는 다음과 같은 URL 체계를 가지고있다.

내가 읽은 문서/예제에서는 그룹 목록이 포함 된 groupfinder 콜백을 제공하여 그룹 수준의 ACS를 구현할 수 있음을 보여주었습니다. editor, admin

권한을 그룹으로 사용하지 않고 대신 페이지 ID를 기반으로 권한을 사용할 수 있습니까?

위 URL 스키마에서 사용자가 /pages을 탐색 할 때 로그인해야합니다. 사용자가 /pages/:id을 탐색 할 때 특정 ID를 볼 수있는 액세스 권한이 있어야합니다. 또는 해당 페이지의 소유자 여야합니다.

댓글과 동일합니다. /page/:id 페이지에 페이지에 대한 액세스 권한이 주어졌지만 댓글을 달지는 못했습니다.

답변

3

이 토론의 목적을 위해 SQLAlchemy를 사용하여 DB와 인터페이스한다고 가정합니다. 당신이 당신의 __init__.pyconfig.add_route('pages', '/pages/{id}')이있는 경우

, 당신은/대체 기본 ACL을 보완하기 위해 사용자 정의 공장를 추가 할 수 있습니다. 예를 들면 :

현재 ACL은 다음과 같이 보일 수 있습니다 :이 인증 된 사용자가 어떤 뷰를 액세스하기 위해 사이트를 방문하는 '인증'의 허가를, 그리고 누구와 어떤보기에 액세스 할 수 있도록 할

class RootFactory(object): 
    __acl__ = [ 
     (Allow, Everyone, 'view'), 
     (Allow, Authenticated, 'auth'), 
    ] 

    def __init__(self, request): 
     self.request = request 

'보기'의 허가.

사용자 지정 공장을 사용하면 RootFactory를 우회하거나 보완 할 수 있습니다.

에 원래 config.add_route을 변경,를 우회하기 ->config.add_route('pages', '/pages/{id}', factory=PageFactory)이 같은 PageFactory 클래스를 만들 :이보기를 가정 한 것입니다

class PageFactory(object): 
    __acl__ = [ 
     (Allow, Everyone, 'view'), 
     (Allow, Authenticated, 'auth'), 
    ] 

    def __init__(self, request): 
     self.request = request 

    from pyramid.security import authenticated_userid 
    user_id = authenticated_userid(self.request) 

    thispage = DBSession.query(Page).filter(Page.id==self.request.matchdict['id']).first() 

    if thispage.user_id == user_id: 
     ## Pyramid allows Everyone, Authenticated, and authenticated_userid 
     ## (each of these is known as a Principal) to be in the second 
     ## position of the ACL tuple 
     acl.append((Allow, user_id, 'edit')) 

매개 변수의 하나로서 permission='edit' 있습니다.당신은 당신이 자신을 반복 할 필요가 없습니다, 당신의 사용자 정의 공장으로 RootFactory 및 보충을 사용하고자하는 경우, 나는이의 시작 부분에 표시 한 바와 같이

이제, 단순히 당신에게 RootFactory를 남겨 당신은 단순히 '관리'와 같은 그룹에 사용자를 배치 할 수 있기 때문에, groupfinder이 방법에 의해, 매우 유용

class PageFactory(RootFactory): 
    @property 
    def __acl__(self): 
     acl = super(PageFactory, self).__acl__[:] ##[:] creates a copy 

     from pyramid.security import authenticated_userid 
     user_id = authenticated_userid(self.request) 

     thispage = DBSession.query(Page).filter(Page.id==self.request.matchdict['id']).first() 

     if thispage.user_id == user_id: 
      acl.append((Allow, user_id, 'edit')) 

     return acl 

이다

, 그리고 : 포스트, 그리고 그와 같이, RootFactory 클래스에서 상속 admin 그룹의 모든 사용자는으로보기에 액세스 할 수 있습니다.또는 permission='whateverelse'을 사용하면 현재 사용자에 대한 그룹화자가 반환되는 그룹 파인더 만 사용할 수 있습니다. 아아아, 내가 빗 나간다. 네가보기를 원하는 것이 아니기 때문이다. 희망이 귀하의 질문에 대한 답변.

6

여기의 기본 원칙은 피라미드 보안 장비가 현재 상황에서 ACL을 검사한다는 것입니다. 이 경우 귀하의 페이지는 사용할 논리적 컨텍스트가됩니다. 첫 번째 단계는 페이지에 대한 컨텍스트 팩토리를 설정하는 것입니다. SQLAlchemy와 URL 디스패치를 ​​사용한다고 가정하면 간단합니다. 이 같은 경로를 등록

config.add_route('page', '/pages/{id:\d+}', factory=page_factory) 

피라미드는 사용자가 직접 확인하지 않아도 페이지 ID가 숫자를해야합니다 확인합니다 경로에 대한 경로에서 약간의 트릭이있다. * page_factory * 메소드에 대한 참고 사항을 유의하십시오. 이제는 다음과 같이 정의 할 수 있습니다.

def page_factory(request): 
    return DBSession.query(Page).get(int(request.matchdict['id'])) 

이 페이지 ID는 경로에서 가져 와서 데이터베이스의 페이지를 조회하는 데 사용됩니다. 여기서 ID가 정수로 변환 될 수 있는지 여부는 확인하지 않습니다. 경로가 이미 직접 확인하기 때문에 그 자리를 비울 수 있습니다.

다음 단계는 페이지에 ACL을 설정하는 것입니다. 가장 간단한 방법은 페이지 클래스에 ACL 속성을 추가하는 것입니다

from pyramid import security 

class Page(BaseObject): 
    @property 
    def __acl__(self): 
     return [(security.Allow, self.userid, 'view')] 

이 ACL은 page.userid에 저장된 ID를 가진 사용자가 해당 페이지를 볼 수있다 피라미드를 알려줍니다. 여기서 중요한 점은 모든 페이지마다 ACL이 다르다는 것입니다. ACL은 데이터베이스의 정보를 기반으로 개별적으로 생성됩니다. 이 경우 self.userid를 사용하십시오.

@view_config(route_name='page', context=Page, permission='view') 
def page_view(context, request): 
    return 'I can see!' 

이 예제는 페이지에 대한 아주 최소한의 ACL을 가지고 있지만, 당신은 당신의 요구에 맞게 그것을 확장 할 수

이제보기에 보기 권한을 사용할 수 있습니다.

view_config에 대한 context = Page 매개 변수에도 유의하십시오.이 뷰는 컨텍스트의 페이지 만 사용되어야한다는 것을 피라미드에 알려줍니다. 컨텍스트 팩토리 (이 예에서는 page_factory)가 일치하는 페이지를 찾지 못하면 Page 인스턴스 대신 None을 반환하므로 피라미드에서는이 뷰를 사용하지 않습니다. 결과적으로 피라미드는 자동으로 발견되지 않은 오류를 생성합니다.

+0

작은 nitpick, 루트 팩토리가'None'을 반환하면 컨텍스트는'None'입니다. 뷰가 발견되지 않으면 자동으로 404가 발생하지 않습니다. 귀하의 예제에서'page_view'가 발견 될 것이지만'None' 문맥이'__acl__'을 갖지 않기 때문에 금지되어 있습니다. –

+0

마지막으로 클릭했습니다. 오늘까지, 나는 ACL과 페이지 클래스와 SQLAlchemy 페이지 '테이블 클래스'사이의 관계를 볼 수 없었다. 지금 모두 함께 조각하기 시작했습니다. – Kane

+0

Michael : 좋은 지적입니다. 이 동작을 얻는 한 가지 방법은 view_config 호출에 context = Page를 추가하는 것입니다. 나는 그것을 반영하기 위해 나의 대답을 업데이트 할 것이다. –

관련 문제