2011-01-10 35 views
8

Vì vậy, tôi đang tạo một trang web nhỏ bằng cách sử dụng CakePHP và ACL của tôi được thiết lập sao cho mỗi lần tạo một nội dung, quy tắc ACL được tạo để liên kết chủ sở hữu nội dung với nội dung thực tế. Điều này cho phép mỗi chủ sở hữu chỉnh sửa/xóa nội dung của riêng họ. Phương pháp này dường như không hiệu quả, bởi vì có một số lượng tương đương các quy tắc ACL như nội dung trong cơ sở dữ liệu. Tôi đã tò mò, làm thế nào để các trang web lớn, với hàng triệu mẩu nội dung, giải quyết vấn đề này?Làm cách nào để các trang web lớn thực hiện các quyền cấp hàng?

Trả lời

10

Với các trang web lớn tôi đã làm việc trên các quyền truy cập được xác định ở cấp ứng dụng. Cơ sở dữ liệu liên kết nội dung với bản ghi của người dùng sau đó trong lớp truy vấn dữ liệu/nghiệp vụ, nó đã xác định xem người dùng có đủ quyền truy cập nội dung hay không.

Đối với trang web lớn có nội dung động, tôi nghĩ điều này có lẽ là cách tốt nhất để xử lý.

EDIT: Để thêm ví dụ cụ thể hơn.

Ví dụ: Ok cho phép nói rằng chúng tôi có một trang lưu trữ tệp đơn giản nơi người dùng chỉ có thể truy cập dữ liệu hoặc dữ liệu của họ đã được người dùng khác chia sẻ rõ ràng.

Kể từ khi ứng dụng này khá đơn giản vì nó chỉ được phục vụ các file nó chỉ có ba bảng cơ sở dữ liệu đó là:

Users Table which has columns: 
     UserId <int> PK 
     UserName <varchar> 
     HashedPassword <varchar> 
Files Table which has columns: 
     FileId <int> PK 
     FileOwnerId <int> FK (this has a foreign key relationship with UserId in the users table) 
     FileName <varchar> 
     MimeType <varchar> 
     FileData <blob> 
SharedFile reference table which has columns: 
     SharedFileIndex <int> PK 
     FileId <int> FK 
     UserId <int> FK 

Bây giờ một số quy tắc cơ bản mà chúng ta sẽ muốn xác định trong lớp truy cập dữ liệu của chúng tôi là khi người dùng đã đăng nhập họ có thể truy cập các tệp mà họ là chủ sở hữu và tệp mà người dùng khác đã chia sẻ với họ. Vì vậy, hoặc thông qua các thủ tục được lưu trữ hoặc xây dựng các truy vấn để gửi đến máy chủ cơ sở dữ liệu tôi sẽ đảm bảo rằng các truy vấn của tôi chỉ trả về những bản ghi mà họ có quyền truy cập vào.

Ở đây GetUsersFileList truy vấn sql cơ bản khi người dùng đăng nhập:

SELECT FileId, FileName, FileType 
FROM Files 
WHERE FileOwnerId = @UserId 

Như bạn có thể thấy ở đây chúng ta đang sử dụng một truy vấn tham số để có được sau đó tập tin người dùng là chủ sở hữu của. Ngoài ra, chúng tôi cũng sẽ truy vấn các tệp được chia sẻ để hiển thị cho người dùng.

Bây giờ nếu chúng ta giả định rằng mỗi file sẽ có url độc đáo riêng của nó như:

http://mydomain.com/filehandler.php?fileId=123546 

Sau đó, khi chúng tôi cố gắng để có được các tập tin chúng tôi sử dụng một truy vấn tương tự như trên để thử và lấy dữ liệu tập tin:

SELECT FileName, FileType, FileData 
FROM Files 
LEFT OUTER JOIN SharedFiles on Files.FileId = SharedFiles.FileId 
WHERE Files.FileId = @FileId AND (FileOwnerId = @UserId OR SharedFiles.UserId = @UserId) 

Vì vậy, bạn sẽ nhìn thấy khi chúng tôi cố gắng để có được các tập tin chúng tôi vẫn đang sử dụng UserId trong truy vấn như vậy, nếu người dùng không có các tập tin hoặc chia sẻ với họ hoặc họ không phải là chủ sở hữu của các tập tin kết quả từ truy vấn sẽ là 0 hàng.

Vì vậy, quyền được xác định bởi những gì người dùng được ánh xạ trong cơ sở dữ liệu nhưng thực thi thực tế bằng cách viết mã truy cập dữ liệu và/hoặc kiểm tra bổ sung trong lớp logic nghiệp vụ của bạn trước khi phân phối nội dung.

EDIT2: Tôi quen thuộc nhất với MSSQL vì vậy các truy vấn của tôi ở trên là trong T-SQL nên cú pháp có thể hơi lệch đối với MySql.

EDIT3: Lớp logic kinh doanh được thay thế bằng lớp truy cập dữ liệu như trong ví dụ này, kiểm tra duy nhất được thực hiện nằm trong chính truy vấn dữ liệu.

EDIT4: Ok đặt trở lại tham chiếu đến lớp logic nghiệp vụ vì các ứng dụng phức tạp hơn sẽ cần các lược đồ quyền phức tạp hơn có thể yêu cầu kiểm tra bổ sung trong lớp logic nghiệp vụ.

+0

Có vẻ thú vị, bạn có thể xây dựng thêm một chút nữa không (ví dụ: thêm một ví dụ nhỏ về cách bạn sẽ thực hiện việc này)? – nico

+0

Chắc chắn. Làm việc trên một bản cập nhật ngay bây giờ. – Adrian

0

Quy tắc tương tự áp dụng cho cả trang web lớn và nhỏ - nếu bạn muốn kiểm soát cụ thể hơn, bạn phải lưu trữ nhiều dữ liệu hơn trong cơ sở dữ liệu. Vấn đề bạn đang cố gắng giải quyết [cho phép người dùng quản lý nội dung của họ] có thể được giải quyết bằng cách sử dụng liên kết id người dùng đơn giản giữa các bảng [ví dụ: users.id < -> articles.userId], không cần phải liên kết mọi hàng với người dùng. Tôi khuyên bạn nên sử dụng nhiều quy tắc chung hơn và chỉ lưu trữ ngoại lệ [ví dụ: cho phép người dùng được chỉ định chỉnh sửa nội dung người dùng khác] dưới dạng dữ liệu ngoài.

2

Thay vì có ACL riêng cho từng thành phần nội dung, bạn có thể có ACL riêng cho từng nhóm quyền khác nhau. Hầu hết các mục nội dung cho một người dùng nhất định sẽ có cùng quyền, vì vậy tất cả các mục nội dung đều có cùng một ACL. Điều này cũng có thể cho phép bạn kiểm tra bộ nhớ cache (ví dụ: "người dùng 123 có quyền đọc ACL 456"). Cuối cùng, bạn sẽ có rất ít ACL - chỉ tất cả các ACL tiêu chuẩn và một vài ngoại lệ.

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