2015-08-18 25 views
5

Tôi đang thiết kế ủy quyền cho một ứng dụng DRF. Tôi cần phải sử dụng vai trò, không chỉ cho phép.Thiết kế ủy quyền dựa trên vai trò Django Rest Framework

Tôi có một mô hình (ví dụ: project) trong đó tôi có một số thông tin (ví dụ: tên, mô tả) có thể được sửa đổi bởi một số vai trò (ví dụ: admin). Nhưng đồng thời có các vai trò khác (ví dụ: worker) không được sửa đổi thông tin đó bên trong mô hình đó nhưng vẫn có thể sửa đổi một số thông tin khác (ví dụ: ngày ban đầu và ngày cuối cùng).

Tôi đã nghĩ hai giải pháp cho vấn đề này. Đầu tiên là đọc yêu cầu HTTP được gửi và xác định các hành động sẽ được thực hiện tùy thuộc vào yêu cầu. Điều này có nghĩa là mỗi khi một trường mới được thêm vào mô hình, tôi sẽ phải sửa đổi logic này. Điều này nghe có vẻ khó khăn để duy trì, là lỗi dễ bị và có thể giới thiệu các lỗ hổng.

Mặt khác, tôi đã nghĩ rằng tôi có thể chia mô hình thành hai mô hình khác nhau. Một trong số chúng chứa dữ liệu chỉ có một vai trò (admin) có thể sửa đổi và một dữ liệu khác xác định dữ liệu khác có thể được sửa đổi bởi cả hai vai trò (admin, worker). Bằng cách này, tôi sẽ không phải phân tích cú pháp yêu cầu HTTP, bởi vì nếu tôi nhận được yêu cầu POST/PUT ảnh hưởng đến mô hình đầu tiên và người dùng có vai trò công nhân, tôi có thể trực tiếp từ chối nó.

Tình huống này xảy ra với nhiều mô hình.

Tôi muốn biết nếu có cách mặc định để đi hoặc nếu tôi đang phát minh lại bánh xe. Tôi nghĩ rằng tình trạng này phải thực sự phổ biến. Ví dụ, tôi có thể nghĩ về một dự án git trong đó một số người dùng có quyền truy cập để làm một việc bên trong một dự án chứ không phải một thứ khác.

ghi chú bổ sung (thông tin phản hồi sẽ được thực sự đánh giá cao):

  • tôi có lẽ hầu hết sẽ sử dụng mô-đun django-role-permissions để thực hiện vai trò và quyền. Tôi không thể sử dụng django được xây dựng trong nhóm bởi vì, mặc dù bạn có thể thêm quyền cho họ, tôi sẽ sử dụng chúng để nhóm người dùng (mà không có bất cứ điều gì để làm với vai trò).

  • Tôi sẽ tạo mối quan hệ giữa vai trò và quyền (quyền dựa trên chuỗi, chẳng hạn như create_project, modify_project_description) trong tệp quyền.

  • Khi nhận được từng yêu cầu, tôi sẽ kiểm tra vai trò nào có quyền thực hiện tác vụ đó và kiểm tra xem người dùng có thuộc bất kỳ vai trò nào hay không (điều hành dựa trên hoạt động, có nghĩa là ở điểm cuối tôi sẽ kiểm tra hoạt động/hành động của vai trò).

Trả lời

1

Sau khi đưa ra một số suy nghĩ, tôi đã tìm thấy hai giải pháp.

Giải pháp đầu tiên là (thay vì chia các mô hình như tôi đã đề cập trong câu hỏi), khai báo các điểm cuối (URL) khác nhau cho từng loại hành động phải xảy ra. Sau đó, tại mỗi điểm cuối, serializer xác định thông số hợp lệ thông qua biến lớp học fields. Điều này có nghĩa rằng nếu một vai trò chỉ có thể cập nhật một số trường nhất định, tôi sẽ tạo một ModelViewSet cho hành động này và trong lớp serializer liên quan đến ModelViewSet này chỉ cho phép một số tham số nhất định.

Giải pháp này có nhiều vấn đề và không hoàn toàn yên tĩnh. Bạn có thể kết thúc với hàng tá URL khác nhau. Trong trường hợp của tôi, với điều kiện API không lớn và các hành động bị hạn chế có thể không có vấn đề gì trong ngắn hạn, nhưng chắc chắn nó sẽ là một vấn đề khi các yêu cầu của ứng dụng thay đổi.

Thứ hai (và lựa chọn) giải pháp là để xác định một phép/vai trò bảng trong đó bạn xác định điểm cuối nơi mà hành động có thể xảy ra (nếu bạn đã xây dựng ứng dụng của bạn trong một cách chính xác nó chỉ có thể là ModelViewSet tên lớp), hành động được thực hiện (danh sách, truy xuất, tạo ...) các trường của mô hình liên quan có thể tương tác và vai trò có thể tương tác với các trường đó.

Tôi khuyên bạn nên sử dụng từ điển làm cấu trúc dữ liệu được sử dụng cho bảng quyền để mỗi lần kiểm tra quyền là O(1).

Bây giờ mỗi lần bạn nhận được yêu cầu đến điểm cuối đó, bạn nên thực hiện kiểm tra quyền sử dụng bảng đó.

Tôi đã thực hiện kiểm tra giấy phép bằng cách ghi đè phương thức check_permissions() trong lớp ModelSetView. Hãy cẩn thận và giữ chức năng gốc check_permissions() trong đó.

2

Âm thanh như bạn muốn bảo mật ở mức độ trường. Bạn có thể xem xét sử dụng các mô hình proxy để cấp quyền truy cập ghi vào một nhóm trường giới hạn cho người dùng bị hạn chế.

Một tùy chọn khác có thể là sử dụng một lớp serializer tùy chỉnh áp dụng chỉ đọc cho một số trường. get_serializer trên một lớp con ViewSet có thể là một nơi tốt để làm trục, bạn nên tìm người dùng hiện tại trong self.request.user.

+1

Bạn xứng đáng nhận được ưu đãi vì tôi sẽ thực hiện mọi thứ bạn đề cập (ngoài mô hình proxy). – newlog

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