2012-04-22 33 views
6

Tôi đang cố gắng triển khai các tính năng Bảo mật của Kim tự tháp trong trang web của mình nhưng tôi đang gặp một số sự cố khi tìm hiểu cách sử dụng nó.Làm cách nào để hạn chế quyền dựa trên ID trang duy nhất trong URL?

Tôi đã đọc hơn this tutorialthis example, cũng như tài liệu Kim tự tháp và tôi không thể tìm ra cách triển khai chính sách ủy quyền cho ID trang đơn.

Ví dụ, tôi có thức truy cập URL sau:

/pages 
/pages/12 

/pages rõ ràng là liệt kê các trang có sẵn và /pages/:id là nơi bạn có thể đọc/bình luận trên trang.

Tài liệu/ví dụ tôi đã đọc đã cho thấy rằng bạn có thể triển khai ACS cấp nhóm bằng cách cung cấp gọi lại groupfinder với danh sách nhóm. Chẳng hạn như editor, admin, v.v.

Làm cách nào để không sử dụng nhóm cho quyền và quyền thay thế dựa trên id trang?

Trong lược đồ URL của tôi ở trên, khi người dùng duyệt đến /pages họ phải đăng nhập. Khi họ duyệt đến /pages/:id, họ phải được cấp quyền truy cập để xem id cụ thể đó. Hoặc, họ phải là chủ sở hữu của trang đó.

Giống như nhận xét. Trên trang /page/:id, họ có thể được cấp quyền truy cập để xem trang nhưng không nhận xét về trang đó.

Trả lời

3

Vì mục đích của cuộc thảo luận này, tôi sẽ giả sử bạn đang sử dụng SQLAlchemy để giao tiếp với DB của bạn.

Nếu bạn có config.add_route('pages', '/pages/{id}') trong __init__.py của bạn, bạn có thể thêm một nhà máy tùy chỉnh để thay thế/bổ sung ACL mặc định của bạn. Ví dụ:

ACL hiện tại của bạn có thể trông như thế này:

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

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

Điều này sẽ cho phép người dùng xác thực để truy cập bất kỳ quan điểm với một sự cho phép của 'auth', và bất cứ ai truy cập trang web của bạn để truy cập vào bất kỳ quan điểm với sự cho phép của 'xem'.

Bằng cách sử dụng nhà máy tùy chỉnh, bạn có thể bỏ qua RootFactory hoặc bổ sung nó.

Để bỏ qua, thay đổi config.add_route ban đầu của bạn để ->config.add_route('pages', '/pages/{id}', factory=PageFactory) và tạo ra một lớp PageFactory như thế này:

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')) 

này là giả định xem bạn có permission='edit' là một trong những thông số của nó.

Bây giờ, nếu bạn muốn sử dụng RootFactory và bổ sung nó với nhà máy tùy chỉnh của bạn, vì vậy bạn không cần phải lặp lại chính mình, chỉ cần để lại cho bạn RootFactory như tôi đã thể hiện ở phần đầu của này môn, kế thừa từ lớp RootFactory, như vậy:

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 

các groupfinderrất hữu ích, bằng cách này, bởi vì khi đó bạn chỉ có thể đặt người dùng trong nhóm, chẳng hạn như 'admin', và tất cả những người trong nhóm quản trị đều có thể truy cập lượt xem với permission='whatever' hoặc permission='whateverelse' mà bạn có thể muốn và không cần Nhà máy, chỉ một kính ngắm nhóm trả về người đánh lừa cho người dùng hiện tại. Than ôi, tôi tiêu hóa, vì đó không phải là những gì bạn đang tìm kiếm. Hy vọng điều này trả lời câu hỏi của bạn.

6

Nguyên tắc cơ bản ở đây là máy móc bảo mật của Kim tự tháp kiểm tra ACL trên ngữ cảnh hiện tại. Trong trường hợp này, trang của bạn sẽ là ngữ cảnh hợp lý để sử dụng. Bước đầu tiên là thiết lập một nhà máy ngữ cảnh cho một trang. Giả sử bạn đang sử dụng SQLAlchemy và công văn URL, điều này rất đơn giản. Đăng ký tuyến đường của bạn như thế này:

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

Có một mẹo nhỏ trong lộ trình làm cho kim tự tháp kiểm tra id trang phải là số để bạn không phải tự mình kiểm tra. Lưu ý tham chiếu đến phương thức * page_factory *. Cho phép xác định rằng bây giờ:

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

Điều này sẽ lấy id trang từ tuyến đường và sử dụng nó để tra cứu trang trong cơ sở dữ liệu của bạn. Lưu ý rằng chúng tôi không kiểm tra xem id có thể được chuyển đổi thành một số nguyên ở đây hay không: chúng tôi có thể thoát khỏi điều đó vì tuyến đường đã kiểm tra trực tiếp.

Bước tiếp theo là thiết lập ACL trên trang. Cách đơn giản nhất là thêm một acl tài sản để bạn Trang lớp:

from pyramid import security 

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

ACL này cho kim tự tháp mà chỉ có người dùng với id lưu trữ trong page.userid được phép xem trang đó. Điều quan trọng để nhận ra ở đây là ACL là khác nhau cho mỗi trang: nó được tạo ra cho mỗi trang riêng biệt dựa trên thông tin trong cơ sở dữ liệu của bạn; trong trường hợp này sử dụng self.userid.

Bây giờ bạn có thể sử dụng xem phép vào xem của bạn:

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

Ví dụ này có một ACL rất tối thiểu cho một trang, nhưng bạn có thể mở rộng đó để phù hợp với nhu cầu của bạn.

Cũng lưu ý tham số context = Page cho view_config: điều này cho biết kim tự tháp rằng chế độ xem này chỉ nên được sử dụng trong ngữ cảnh là Trang. Nếu nhà máy ngữ cảnh (page_factory trong ví dụ này) không tìm thấy một trang phù hợp, nó sẽ trả về None thay vì một cá thể trang, do đó, khung nhìn này sẽ không được sử dụng bởi kim tự tháp. Kết quả là kim tự tháp sẽ tự động tạo ra lỗi không tìm thấy.

+0

nitpick nhỏ, nếu nhà máy gốc của bạn trả về 'Không có', thì ngữ cảnh là 'Không có', 404 sẽ không tự động xảy ra trừ khi không thể tìm thấy chế độ xem. Trong ví dụ của bạn 'page_view' sẽ được tìm thấy, nhưng một lệnh cấm sẽ xảy ra do ngữ cảnh' None' không có '__acl__'. –

+0

Nó cuối cùng đã được nhấp. Cho đến ngày hôm nay, tôi đã không thấy mối quan hệ nào giữa lớp Page với lớp bảng ACL và lớp SQLAlchemy Page '. Bây giờ tất cả bắt đầu với nhau. – Kane

+0

Michael: điểm tốt. Một cách để thực hiện hành vi đó là thêm context = Page vào lời gọi view_config. Tôi sẽ cập nhật câu trả lời của tôi để phản ánh điều đó. –

Các vấn đề liên quan