6

Web サイトに Pyramid のセキュリティ機能を実装しようとしていますが、使い方がわかりません。

このチュートリアルこの例、および Pyramid のドキュメントを読んでいますが、単一ページ ID の承認ポリシーを実装する方法がわかりません。

たとえば、次の URL スキームがあります。

/pages
/pages/12

/pages明らかに利用可能なページ/pages/:idがリストされており、ページを読んだりコメントしたりできる場所です。

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

アクセス許可にグループを使用せずに、ページ ID に基づく権利を使用するにはどうすればよいですか?

上記の URL スキームでは、ユーザーが/pagesを閲覧するときはログインする必要があります/pages/:id。または、そのページの所有者である必要があります。

コメントと同じ。ページ上で、/page/:idページを表示するアクセス権は付与されているが、コメントは付与されていない可能性があります。

4

2 に答える 2

6

ここでの基本原則は、Pyramid のセキュリティ機構が現在のコンテキストで 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プロパティを Page クラスに追加することです。

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 が返されるため、このビューはピラミッドによって使用されません。その結果、ピラミッドは自動的に見つからないエラーを生成します。

于 2012-04-22T15:49:13.227 に答える
3

この説明では、SQLAlchemy を使用して DB とやり取りしていると仮定します。

にある場合はconfig.add_route('pages', '/pages/{id}')カスタム ファクトリ__init__.pyを追加して、デフォルトの ACL を置き換え/補足することができます。例えば:

現在の ACL は次のようになります。

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

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

これにより、認証されたユーザーは「auth」の権限ですべてのビューにアクセスでき、サイトにアクセスするすべてのユーザーは「view」の権限ですべてのビューにアクセスできます。

カスタム factoryを使用することで、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'そのパラメーターの 1 つとして持っていることを前提としています。

ここで、RootFactory を使用してカスタム ファクトリで補足したい場合は、同じことを繰り返す必要がありません。この投稿の冒頭で示したように、単に RootFactory のままにして、RootFactory クラスから継承します。 、 そのような:

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

ちなみに、グループファインダー非常に便利です。ユーザーを「admin」などのグループに配置するだけで、admin グループ内のすべてのユーザーがビューにアクセスできるpermission='whatever'ためpermission='whateverelse'、ファクトリは必要なく、現在のユーザーのグループリストを返す groupfinder。残念ながら、それはあなたがしようとしていたことではないので、脱線します。これがあなたの質問に答えることを願っています。

于 2012-04-22T14:48:16.797 に答える