Đánh giá mã động trong Java - Thông minh hay cẩu thả?


30

Tôi đang cố gắng tạo một khung ACL linh hoạt trong Java cho ứng dụng của mình.

Nhiều khung ACL được xây dựng trên danh sách trắng các quy tắc, trong đó quy tắc ở dạng chủ sở hữu: hành động: tài nguyên . Ví dụ,

  • "JOHN có thể XEM tài nguyên FOOebar-1"
  • "MARY có thể XEM tài nguyên FOOebar-1"
  • "MARY có thể EDIT tài nguyên FOOebar-1"

Điều này hấp dẫn bởi vì các quy tắc có thể dễ dàng được tuần tự hóa / duy trì vào cơ sở dữ liệu. Nhưng ứng dụng của tôi có logic kinh doanh phức tạp. Ví dụ,

  • "Tất cả người dùng trong bộ phận 1 với hơn 5 năm thâm niên có thể XEM tài nguyên FOOebar-1, người khác không được ủy quyền"
  • "Tất cả người dùng trong bộ phận 2, nếu ngày sau ngày 15/03/2016, có thể XEM tài nguyên FOOebar-2, nếu không thì không được phép"

Theo suy nghĩ đầu tiên, sẽ là một cơn ác mộng khi nghĩ ra một lược đồ cơ sở dữ liệu có thể xử lý các quy tắc vô cùng phức tạp như các quy tắc này. Do đó, dường như tôi sẽ cần phải "nướng" chúng vào ứng dụng đã biên dịch, đánh giá chúng cho từng người dùng và sau đó tạo ra chủ sở hữu: hành động: quy tắc tài nguyên do kết quả của việc đánh giá. Tôi muốn tránh nướng logic vào ứng dụng được biên dịch.

Vì vậy, tôi đã nghĩ đến việc biểu diễn một quy tắc dưới dạng vị ngữ : hành động: tài nguyên , trong đó vị từ là biểu thức boolean xác định xem người dùng có được phép hay không. Vị ngữ sẽ là một chuỗi biểu thức JavaScript có thể được đánh giá bởi công cụ Rhino của Java. Ví dụ,

  • return user.getDept() == 1 && user.seniority > 5;

Khi làm như vậy, các vị từ có thể dễ dàng được lưu vào cơ sở dữ liệu.

Điều này có thông minh không? Đây có phải là cẩu thả ? Đây có phải là phô trương ? Đây có phải là quá thiết kế ? Điều này có an toàn không (rõ ràng, Java có thể sandbox động cơ Rhino).


8
Lợi ích của việc cố gắng đẩy các quy tắc kinh doanh này vào cơ sở dữ liệu qua việc đưa logic vào ứng dụng được biên dịch là gì?
Winston Ewert

6
@WinstonEWert Việc bên ngoài các quy tắc loại bỏ nhu cầu biên dịch lại và phân phối lại ứng dụng nếu một quy tắc được thay đổi, thêm hoặc xóa.
Twittopher

2
@WinstonEwert có liên quan: Có quá nhiều câu lệnh if-

2
Câu hỏi thú vị! Tôi muốn thấy một câu trả lời không tập trung vào bảo mật quá nhiều mà thay vào đó là các khía cạnh bảo trì, độ tin cậy và dễ sử dụng của một giải pháp như vậy.
oliver

6
Điều này nghe có vẻ giống với quy tắc email của Outlook , về cơ bản là một công cụ quy tắc có thể được cấu hình bởi người dùng.

Câu trả lời:


37

Đường ống dữ liệu động vào một trình thông dịch ngôn ngữ thực hiện của bạn thường là một ý tưởng tồi, vì nó leo thang tiềm năng tham nhũng dữ liệu thành tiềm năng tiếp quản ứng dụng độc hại. Nói cách khác, bạn đang đi trên con đường của bạn để tạo ra một tiêm mã dễ bị tổn thương.

Vấn đề của bạn có thể được giải quyết tốt hơn bằng cách công cụ quy tắc hoặc có thể là ngôn ngữ dành riêng cho tên miền (DSL) . Nhìn những khái niệm đó lên, không cần phải phát minh lại bánh xe.


16
Nhưng liệu JavaScript có được sử dụng như một ngôn ngữ viết kịch bản giống như DSL ở đây không? Chúng tôi thiết lập dữ liệu cần thiết (chỉ đọc), bọc đoạn mã trong một chức năng và đánh giá nó một cách an toàn. Vì mã không thể làm bất cứ điều gì ngoại trừ trả lại một boolean, sẽ không có cơ hội độc hại nào ở đây.
amon

6
@Twittopher Kéo toàn bộ công cụ JavaScript để đánh giá một số vị từ có vẻ như 1) hoàn thành quá mức, 2) rủi ro và 3) dễ bị lỗi đối với tôi. Trong trường hợp, bạn đã sử dụng ==thay vì ===trong ví dụ của bạn. Bạn có thực sự muốn cung cấp sự hoàn chỉnh turing khi tất cả các quy tắc nên luôn luôn chấm dứt? Thay vì nhảy qua các vòng để đảm bảo tất cả các tương tác giữa Java và JavaScript là tốt hơn, tại sao bạn không viết một trình phân tích cú pháp và trình thông dịch đơn giản như Kilian đề xuất? Sẽ dễ dàng hơn nhiều để điều chỉnh theo nhu cầu của bạn và an toàn. Sử dụng ANTLR hoặc một cái gì đó.
Doval

6
@Doval Viết một DSL nhỏ không chính xác là khoa học tên lửa và tôi có thể tạo ra một ngôn ngữ đơn giản trong 3 giờ đến 5 ngày. Nhưng điều này có vẻ như 1) hoàn thành quá mức, 2) rủi ro và 3) dễ bị lỗi đối với tôi. Bạn có thực sự muốn viết cả một ngôn ngữ nhỏ không? Điều gì xảy ra nếu một số quy tắc kinh doanh phức tạp hơn dự kiến ​​và cần một ngôn ngữ đầy đủ tính năng? Bạn đang bị hội chứng không phát minh ở đây? Thay vì phát minh lại bánh xe, tại sao bạn không sử dụng ngôn ngữ hiện có? Sử dụng một ngôn ngữ đã được thử nghiệm chiến đấu dễ dàng hơn nhiều.
amon

14
@amon Khi điều đó xảy ra, bạn tìm thấy một công cụ quy tắc thực sự (mà JavaScript không phải) như Killian đã nói. Để đánh đồng rủi ro của cả hai phương pháp là sai lệch. Chỉ cần một thiếu sót để phá hủy tất cả những nỗ lực của bạn trong việc đảm bảo một thông dịch viên cho một ngôn ngữ hoàn chỉnh; đó là một quá trình trừ Thật khó khăn hơn nhiều khi vô tình làm cho một DSL nhỏ trở nên nguy hiểm; đó là một quá trình phụ gia. Loại lỗi bạn có thể mắc phải là diễn giải cây cú pháp không chính xác và đó có thể là đơn vị được kiểm tra. Có lẽ bạn sẽ không vô tình cung cấp cho trình thông dịch định dạng khả năng một ổ cứng.
Doval

4
@amon: Ngay cả khi đoạn trích js có thể không có tác dụng phụ, nó có thể chọn không trả về giá trị boolean:while (true) ;
Bergi

44

Tôi đã làm điều này, và tôi khuyên bạn không nên.

Những gì tôi đã làm là viết tất cả logic nghiệp vụ trong Lua và lưu trữ tập lệnh Lua đó trong cơ sở dữ liệu. Khi ứng dụng của tôi khởi động, nó sẽ tải và thực thi tập lệnh. Bằng cách đó tôi có thể cập nhật logic kinh doanh cho ứng dụng của mình mà không cần phân phối nhị phân mới.

Tôi luôn luôn thấy rằng tôi luôn cần cập nhật nhị phân khi thực hiện thay đổi. Một số thay đổi là trong tập lệnh Lua, nhưng tôi luôn có một danh sách các thay đổi cần phải thực hiện, và vì vậy tôi hầu như luôn luôn phải thực hiện một số thay đổi trong nhị phân và một số thay đổi trong tập lệnh Lua. Trí tưởng tượng của tôi rằng tôi có thể tránh phân phối nhị phân mọi lúc chỉ đơn giản là không thoát ra được.

Những gì tôi thấy hữu ích hơn nhiều là để dễ dàng phân phối nhị phân. Ứng dụng của tôi tự động kiểm tra các bản cập nhật khi khởi động, tải xuống và cài đặt bất kỳ bản cập nhật nào. Do đó, người dùng của tôi luôn ở trên các tệp nhị phân mới nhất mà tôi đã đẩy. Hầu như không có sự khác biệt giữa thay đổi trong nhị phân và thay đổi trong các tập lệnh. Nếu tôi làm điều đó một lần nữa, tôi sẽ nỗ lực hơn nữa để làm cho bản cập nhật trở nên liền mạch.


3

Tôi sẽ không có cơ sở dữ liệu chứa mã. Nhưng bạn có thể làm điều gì đó tương tự bằng cách có cơ sở dữ liệu chứa các tên hàm và sau đó sử dụng sự phản chiếu để gọi chúng. Khi bạn thêm một điều kiện mới, bạn phải thêm nó vào mã và cơ sở dữ liệu của bạn, nhưng bạn có thể kết hợp các điều kiện và tham số được truyền cho chúng để tạo ra các đánh giá khá phức tạp.

Nói cách khác, nếu bạn có các bộ phận được đánh số, bạn sẽ dễ dàng kiểm tra UserDepidorIs và kiểm tra TodayIsSau đó, sau đó kết hợp chúng để có một Bộ = 2 và Hôm nay> 15/03/2016. Nếu sau đó bạn muốn có một kiểm tra TodayIsB Before để bạn có thể kết thúc ngày cấp phép, bạn phải viết hàm TodayIsB Before.

Tôi đã không làm điều này cho quyền của người dùng, nhưng đã thực hiện nó để xác thực dữ liệu, nhưng nó sẽ hoạt động.


2

XACML là giải pháp bạn thực sự đang tìm kiếm. Nó là một loại công cụ quy tắc chỉ tập trung vào kiểm soát truy cập. XACML, một tiêu chuẩn được xác định bởi OASIS, định nghĩa ba phần:

  • một kiến ​​trúc
  • một ngôn ngữ chính sách (đó thực sự là những gì bạn muốn)
  • sơ đồ yêu cầu / phản hồi (cách bạn yêu cầu quyết định ủy quyền).

Kiến trúc như sau:

  • Điểm quyết định chính sách (PDP) là phần cốt lõi của kiến ​​trúc. Nó là thành phần đánh giá các yêu cầu ủy quyền đến đối với một nhóm chính sách đã biết
  • Điểm thực thi chính sách (PEP) là đoạn mã bảo vệ ứng dụng / API / dịch vụ của bạn. PEP chặn yêu cầu nghiệp vụ, tạo yêu cầu ủy quyền XACML, gửi nó đến PDP, nhận phản hồi và thực thi quyết định bên trong phản hồi.
  • Điểm thông tin chính sách (PIP) là thành phần có thể kết nối PDP với các nguồn dữ liệu bên ngoài, ví dụ LDAP, cơ sở dữ liệu hoặc dịch vụ web. PIP có ích khi PEP gửi yêu cầu, ví dụ: "Alice có thể xem tài liệu # 12 không?" và PDP có chính sách yêu cầu độ tuổi của người dùng. PDP sẽ yêu cầu PIP "cho tôi tuổi của Alice" và sau đó sẽ có thể xử lý các chính sách.
  • Điểm quản trị chính sách (PAP) là nơi bạn quản lý toàn bộ giải pháp XACML (xác định các thuộc tính, chính sách bằng văn bản và định cấu hình PDP).

Ngôn ngữ đánh dấu kiểm soát truy cập có thể mở rộng - Kiến trúc XACML

Đây là trường hợp sử dụng đầu tiên của bạn trông như thế nào:

/*
 * All users in department 1 with over 5 years of seniority can VIEW resource FOOBAR-1, else not authorized
 * 
 */
 policy departmentOne{
    target clause department == 1
    apply firstApplicable
    /**
     * All users in department 1 with over 5 years of seniority can VIEW resource FOOBAR-1, else not authorized
     */
    rule allowFooBar1{
        target clause resourceId=="FOOBAR-1" and seniority>=5 and actionId=="VIEW"
        permit
    }
    rule denyOtherAccess{
        deny
    }

 }

Trường hợp sử dụng thứ hai của bạn sẽ là:

 /*
  * "All users in department 2, if the date is after 03/15/2016, can VIEW resource FOOBAR-2, else not authorized"
  *  
  */
  policy departmentTwo{
    target clause department == 1
    apply firstApplicable
    rule allowFooBar2{
        target clause resourceId=="FOOBAR-1" and seniority>=5 and currentDate>"2016/03/15":date and actionId=="VIEW"
        permit
    }
    rule denyOtherAccess{
        deny
    }
  }

Bạn có thể kết hợp cả hai trường hợp sử dụng thành một chính sách bằng cách sử dụng tài liệu tham khảo:

  policyset global{
    apply firstApplicable
    departmentOne
    departmentTwo
  }

Và bạn đã hoàn thành!

Bạn có thể đọc thêm về XACML và ALFA từ:


0

Những gì bạn thực sự muốn ở đây là XACML . Nó khá nhiều cung cấp cho bạn chính xác những gì bạn muốn. Bạn không nhất thiết phải thực hiện kiến ​​trúc đầy đủ với tất cả các vai trò được tách biệt hoàn toàn ... nếu bạn chỉ có một ứng dụng duy nhất, bạn có thể thoát khỏi việc tích hợp PDP và PEP vào ứng dụng của bạn với balana và PIP là bất cứ điều gì cơ sở dữ liệu người dùng hiện tại của bạn là.

Bây giờ, bất cứ nơi nào trong ứng dụng của bạn cần ủy quyền một cái gì đó, bạn tạo một yêu cầu XACML có người dùng, hành động và bối cảnh và công cụ XACML sẽ đưa ra quyết định dựa trên các tệp chính sách XACML mà bạn đã viết. Các tệp chính sách này có thể được giữ trong cơ sở dữ liệu hoặc trên hệ thống tệp hoặc bất cứ nơi nào bạn muốn giữ cấu hình. Axiomatics có một giải pháp thay thế tuyệt vời cho biểu diễn XACML XML có tên ALFA dễ đọc hơn một chút so với XML thô và một plugin Eclipse để tạo XACML XML từ các chính sách ALFA.


1
Làm thế nào để trả lời câu hỏi này?
gnat

Anh ấy đặc biệt cố gắng thực hiện một hệ thống ủy quyền được cấu hình bên ngoài. XACML là một hệ thống ủy quyền được cấu hình bên ngoài sẵn sàng bao gồm cả trường hợp sử dụng cụ thể của anh ấy. Tôi sẽ thừa nhận rằng nó có thể không phải là một câu trả lời tuyệt vời cho câu hỏi chung hơn về thực thi mã động, nhưng nó là một giải pháp tốt cho câu hỏi cụ thể của anh ấy.
gregsymons 30/03/2015

0

Chúng tôi đã làm điều này tại công ty hiện tại của tôi và chúng tôi rất hài lòng với kết quả.

Biểu thức của chúng tôi được viết bằng js và chúng tôi thậm chí sử dụng chúng để hạn chế kết quả mà người dùng có thể nhận được từ truy vấn ElasticSearch.

Bí quyết là đảm bảo có đủ thông tin để đưa ra quyết định, để bạn thực sự có thể viết bất cứ điều gì bạn muốn mà không cần thay đổi mã, nhưng đồng thời giữ cho nó nhanh chóng.

Chúng tôi không thực sự lo lắng với các cuộc tấn công tiêm mã, vì các quyền được viết bởi những người không có nhu cầu tấn công hệ thống. Và điều tương tự cũng áp dụng cho các cuộc tấn công DOS nhưwhile(true) ví dụ. Quản trị viên của hệ thống không cần phải làm điều đó, họ có thể xóa quyền của mọi người ...

Cập nhật:

Một cái gì đó như XACML dường như tốt hơn như là một điểm quản lý xác thực trung tâm cho một tổ chức. Trường hợp sử dụng của chúng tôi hơi khác nhau ở chỗ khách hàng của chúng tôi về cơ bản không có bộ phận CNTT để điều hành tất cả. Chúng tôi cần một cái gì đó khép kín nhưng cố gắng duy trì sự linh hoạt nhất có thể.

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.