2012-04-22 3 views
6

私は自分のウェブサイトにPyramidのセキュリティ機能を実装しようとしていますが、使用方法を理解する上で問題があります。URLの単一ページIDに基づいてアクセス権を制限するにはどうすればよいですか?

私はthis tutorialthis exampleとPyramidドキュメントを読んできました.1ページIDの認可ポリシーの実装方法を理解できません。

/pages 
/pages/12 

/pages明らかに使用可能なページを一覧表示し、ページ上/コメントを読むことができる場所/pages/:idは次のとおりです。

は例えば、私は、次のURLスキームを持っています。

私が読んだドキュメンテーション/例では、グループリストと共にgroupfinderコールバックを提供することで、グループレベルのACSを実装できることが示されています。 editor,adminなど

グループを権限に使用せず、代わりにページIDに基づいて権限を使用できますか。

上記の私のスキームでは、ユーザが/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 

これは、認証されたユーザーは、「認証」の許可を得て、任意のビューにアクセスできるようになると、あなたのサイトを訪れた誰もが持つすべてのビューにアクセスするには'view'の許可。

カスタムファクトリーを使用すると、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を使用してデータベース内のページを検索します。ここで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パラメータにも注意してください。これは、このビューをコンテキストのみで使用する必要があることをpyramidに通知します。コンテキストファクトリ(この例ではpage_factory)が一致するページを見つけなかった場合、Pageインスタンスの代わりにNoneが返されるため、このビューはピラミッドでは使用されません。その結果、ピラミッドは自動的に見つからないエラーを生成します。

+0

あなたのルートファクトリが 'None'を返した場合、コンテキストは' None'です。ビューが見つからない限り自動的に404は発生しません。あなたの例では、 'page_view'が見つかりましたが、' None'が '__acl__'を持たないコンテキストのため禁止されています。 –

+0

最後にクリックされました。今日までは、PageクラスとACLとSQLAlchemy Pageの 'table class'との間には関係がありませんでした。それはすべて今一緒に彫り始めている。 – Kane

+0

マイケル:良い点。その動作を行う1つの方法は、view_config呼び出しでcontext = Pageを追加することです。私はそれを反映するために私の答えを更新します。 –

関連する問題