API REST dựa trên vai trò?


27

Tôi đang xây dựng API REST mà một số người dùng có vai trò khác nhau sẽ có quyền truy cập vào tài nguyên mà nó chứa.

Để giữ cho phạm vi đơn giản, hãy lấy miền "học sinh / giáo viên / lớp":

GET /students là tài nguyên để truy cập.

Người dùng có thể có các vai trò như Học sinh và / hoặc Giáo viên

Học sinh sẽ chỉ có quyền truy cập vào các sinh viên của lớp học của họ. Giáo viên sẽ có quyền truy cập vào các sinh viên của các lớp học họ dạy. Một số sử dụng có thể là một học sinh VÀ cũng dạy các lớp khác. Họ phải có quyền truy cập vào các sinh viên của lớp VÀ sinh viên của các lớp họ dạy.

Lý tưởng nhất là tôi muốn thực hiện điều này như hai chức năng - một chức năng cho mỗi vai trò và sau đó "hợp nhất" nếu người dùng có nhiều vai trò.

Câu hỏi của tôi là: Tôi nên sử dụng mẫu nào để thực hiện điều này?

Bên ngoài

  • Tôi có nên tách API của mình cho mỗi vai trò không? GET /teacher/studentsGET /student/studentsnó dường như không đúng với tôi.
  • Giữ cho tất cả tôi là một tài nguyên (ưu tiên)

Nội bộ

Làm thế nào nó nên được thực hiện trong nội bộ?

  • Mọi phương pháp có nên bắt đầu bằng một công tắc LỚN / nếu mỗi vai trò không?
  • Tôi có nên thực hiện một kho lưu trữ cho mỗi vai trò?
  • Có một mẫu thiết kế sẽ giúp tôi đạt được điều này?

Như một nhận xét phụ: Tôi đang sử dụng ASP.NET Web APIEntity Framework 6 , nhưng nó thực sự không quan trọng đối với việc triển khai khái niệm.


3
"đây là một câu hỏi hay, tôi muốn biết liệu bạn có đưa ra giải pháp cho vấn đề đó không, vì tôi đang cố gắng làm điều gì đó tương tự. Điều tôi nghĩ nên là: Đầu tiên, chúng tôi sẽ triển khai một api trả về tất cả dữ liệu cần thiết , sau đó mỗi khách hàng sẽ kết nối không trực tiếp với api mà với một proxy sẽ chịu trách nhiệm lọc dữ liệu theo vai trò từ người dùng đó "
Cleiton

Câu trả lời:


11

Bạn nên kiến ​​trúc API xung quanh các tài nguyên, không phải xung quanh các vai trò, ví dụ:

/rest/students

bất cứ ai có vai trò cho phép họ nhìn thấy học sinh có thể truy cập được.

Trong nội bộ, bạn đang thực hiện bảo mật dựa trên vai trò. Cách bạn thực hiện điều đó phụ thuộc vào chi tiết ứng dụng của bạn, nhưng giả sử bạn có một bảng vai trò, mỗi người có một hoặc nhiều vai trò và những vai trò đó quyết định những gì mỗi người có thể truy cập. Bạn đã nêu các quy tắc để truy cập sinh viên:

  • sinh viên có thể truy cập sinh viên trong các lớp họ tham gia
  • giáo viên có thể tiếp cận học sinh trong các lớp học

Vì vậy, khi một người gọi:

/rest/students

bạn gọi một phương thức tiếp cận sinh viên, chuyển qua vai trò của người đó. Đây là một số mã giả:

roles = person.roles; //array
students = getStudents( roles );
return students;

và trong phương pháp đó, bạn có thể nhận các sinh viên cho từng vai trò bằng các cuộc gọi riêng biệt, ví dụ:

factory = getFactory();
classes= [];
students = [];
for( role in roles ){
    service = factory.getService( role );
    // implementation details of how you get classes for student/teacher are hidden in the service
    classes = classes.merge( service.getClasses( person ) );
    // classes[] has class.students[]
    // loop on classes and add each student to students, or send back classes with nested students? depends on use case
  }
}

Đó là một ý tưởng rất sơ bộ cho những gì bạn có thể làm và không nhất thiết phải phù hợp với nhu cầu cụ thể của bạn, nhưng nó sẽ cho bạn cảm giác về những phần liên quan. Nếu bạn muốn trả lại các lớp học với mỗi học sinh được liệt kê, đây là một cách tiếp cận tốt. Nếu bạn chỉ muốn các sinh viên, bạn có thể trích xuất chúng từ mỗi lớp và hợp nhất chúng vào một bộ sưu tập của sinh viên.

Không, bạn không nên có một kho lưu trữ riêng cho mỗi vai trò. Tất cả vai trò là xác định cách bạn có được dữ liệu và có thể những gì bạn có thể làm với dữ liệu (ví dụ: Giáo viên có thể nhập điểm sinh viên). Các dữ liệu là như nhau.

Đối với các mẫu, phương pháp này đang sử dụng Mô hình nhà máy để trừu tượng hóa dịch vụ lấy dữ liệu dựa trên vai trò. Có thể có hoặc không phù hợp để có các dịch vụ riêng biệt theo vai trò. Tôi thích cách tiếp cận này vì nó giảm thiểu số lượng mã ở mỗi giai đoạn của chương trình và làm cho nó dễ đọc hơn một khối chuyển đổi hoặc khối.


1
Cảm ơn vi đa trả lơi. Tôi cuối cùng đã làm một cái gì đó như những gì bạn đề nghị. Bằng cách sử dụng LINQ2SQL (C #), tôi có thể chuyển truy vấn cho từng "vai trò" và áp dụng vị trí cho từng vai trò mà người dùng có. Kết quả sẽ là một câu lệnh sql với điều kiện "HOẶC" cho mỗi vai trò mà người dùng có quyền truy cập. Nếu không có vai trò nào được gán cho người dùng thì tôi chỉ cần trả về Enumarable.Empty () người gọi.
Casper Jensen

0

Tìm một cây bút và một tờ giấy và bắt đầu mô hình hóa hệ thống của bạn.

Bạn sẽ thấy rằng bạn có thể cần một thực thể miền gọi là PERSON. Vì cả SINH VIÊN và GIÁO VIÊN "là một" NGƯỜI, bạn có thể tạo một thực thể trừu tượng được gọi là CÁ NHÂN với các thuộc tính chung như tên, họ, v.v ... MỘT GIÁO VIÊN -> là - a -> Người. Bây giờ bạn có thể thử tìm các đặc điểm cho GIÁO VIÊN không áp dụng cho SINH VIÊN; ví dụ: MỘT GIÁO VIÊN dạy LỚP (es) về một hoặc nhiều ĐỐI TƯỢNG.

Thực thi bảo mật được coi là một khía cạnh phi chức năng của ứng dụng của bạn. Đó là một mối quan tâm xuyên suốt nên được xử lý bên ngoài "logic kinh doanh" của bạn. Như @Robert Munn chỉ ra, (các) ROLE nên được duy trì ở một nơi. Việc sử dụng các vai trò để hạn chế quyền truy cập vào một số chức năng khá thô và khái niệm này được gọi là kiểm soát truy cập dựa trên vai trò (RBAC).

Để xác minh xem giáo viên có được phép xem điểm của học sinh hay không, nên được thể hiện trong mô hình miền của bạn. Nói một giáo viên có một lớp học về lập trình môn học. Bạn có thể sẽ thể hiện trong mô hình của bạn rằng sinh viên tham dự các lớp học cho các môn học khác nhau. Đây là nơi logic ứng dụng / kinh doanh khởi động. Đây là logic mà bạn có thể xác minh bằng cách sử dụng phát triển dựa trên thử nghiệm.

Bạn nên phân chia tài nguyên của mình để làm cho ứng dụng của bạn có thể kiểm tra và mô-đun.

Dù sao, cách tốt nhất để thực sự thể hiện điều tôi muốn nói là hiển thị nó bằng mã :) Đây là trang GitHub: https://github.com/thomasandersen77/role-basing-rest-api

Chúc may mắn :)


3
liên kết của bạn đã biến mất ...
Cleiton
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.