2015-07-19 68 views
2

我工作的一個程序機器人這種結構中管理隱私(我會包括哪些層的笑只做)大型程序

  • 層A - GUI簡單的界面來處理按鈕,遊戲杆等。將這些值轉換成命令發送到控制界面。

  • 層B - 控制從GUI數據庫,並命令請求評估設備讀/寫的條目,以便計算用於數據庫

  • 層C的新設備 - 寫 - 條目 - 設備的數據庫邏輯表示,創建書面和從設備

  • 層d讀值的歷史 - 硬件會談物理硬件。將設備寫入條目轉換爲命令並將它們發送到設備。使用設備中的值更新數據庫設備讀取條目。

我想創建一個java應用程序,其中沒有圖層能夠調用超過一層以上或以下的功能。

是否有可能使用包隱私或像工廠這樣的模式來創建項目結構,這使代碼無法進入,讓我們說層A,從層D或C導入任何東西?

回答

2

這不是您可以單獨使用訪問修飾符實現的功能。

你也不能通過(以某種方式)控制import ...因爲Java語言不會對導入進行任何(額外)限制。 (import指令實際上只是語法糖,因此您無需在任何地方使用完全限定的名稱。)

那麼您還能做什麼?

  • 您可以嘗試實施運行時限制以防止錯誤的層訪問工廠對象。但是這樣的限制很容易被顛覆,故意或意外。

  • 您可以使用某種內部「能力」或「憑證」機制,但很難看出您將如何防止憑證泄漏。 (如果證書是由安全管理器管理(見下文)可能的工作,但是這使問題更加複雜。)

我認爲你可以做到這將是實現一個自定義的唯一方法SecurityManager ,並在每次發生潛在的層交叉呼叫時執行安全檢查。例如,安全管理器可能(雖然很昂貴)檢查調用堆棧以查找調用它的方法/類/包。您還需要關閉可用於(平凡)顛覆安全管理器的某些反射操作。實質上,除了內環之外的所有內容都需要被視爲「不可信」的代碼。老實說,用一個具有「防黑客」安全性的JVM實現這種事情可能超出了凡人的能力。 (太陽/甲骨文還沒有成功尚未....)


其他替代方案:

  • 依靠程序員的自律。

  • 依靠代碼庫的靜態分析;例如通過記錄訪問規則的註釋提供幫助。你需要編寫你自己的代碼分析器來做到這一點。

  • 在層之間使用地址空間分隔以及佔用空間小且安全的API。 (我們不再談論一個單一的常規JVM這裏...)

+0

剛剛向Michael Aaron Safyan提出了同樣的問題,但在您看來,這些昂貴/涉及的方法對於清晰的代碼維護來說是否現實?還是程序員自律? – flakes

+0

如果您只關心代碼可維護性,程序員紀律就足夠了。 IMO。 –

2

TL; DR沒有一個靈丹妙藥解決了這個,但很多不同的工具來利用

有很多種不同的技術來隔離軟件應用程序的不同部分,但我不認爲有任何解決方案可以解決所有問題。一些構建系統可以限制目標之間的依賴關係(例如,Bazel在構建目標上具有visibility屬性,可以阻止一個目標依賴於另一個目標,即使它們通過Java的類可見性彼此都可見),這些目標可以與Java內置可見性。例如:

// Foo.java 
package com.yourcompany.foo; 
public class Foo {} 

// Build rule for Foo.java 
java_library(
    name = "Foo", 
    srcs = ["Foo.java"], 
    # Restricts visibility to this directory, even though 
    # the class visibility was "public" 
    visibility = ["//visibility:private"], 
) 

// Bar.java 
package com.yourcompany.bar; 

import com.yourcompany.foo.Bar; // prevented by build visibility system 

public class Bar { 
    Foo foo = new Foo(); 
} 

另外,也可以使用接口來介導的邏輯組件之間的所有交互,並隱藏這些接口的實現(例如,僅通過服務註冊表接口或通過接口依賴注入暴露實現)。例如,對於Dagger,可以創建用於每個層的單獨component,這將允許你寫類似的代碼:

final class ControllerImpl implements Controller { 
    // Since "ControllerImpl" is instantiated/wired into the 
    // controller layer, the database dependency is available/
    // exposed for injection within this layer. The access control is 
    // strictly performed by the way the dependencies are wired. 
    @Inject 
    public ControllerImpl(Database database) { 
    // ... 
    } 
} 

除了上述,可以使用依賴關係分析/依賴性分析測試或commit鉤子自動檢測依賴性規則違規(並根據它們觸發錯誤/拒絕提交)。例如,一個窮人的解決方案就是簡單地掃描每個文件的包聲明及其導入語句,然後採用一些啓發式方法來檢測不良依賴。

另一種方法是將不同的組件捆綁到單獨的JAR中,並使用自定義的ClassLoader加載它們,這樣可以防止使用反射進行非法訪問(否則可能會繞過任何程序結構)。

除了自動化方法,手動方法也有其價值。手動方法包括在代碼審查和審計期間執行的常規代碼審查和策略。

總之,沒有一個正確的答案。有必要結合使用幾種不同的方法,具體取決於這種分離的重要性。

+0

哇,我不知道這實際上會有多大的問題!限制圖層訪問的想法是確保代碼可維護。這些解決方案是否適合課外項目,這可能只會持續一年或兩年的上限?或者像Stephen C所說的那樣,「依靠程序員紀律」是一種更合適的方法? – flakes

+1

好的。如果它只是簡潔而不是嚴格的隱私問題,那麼通過接口調解控制,使用注入框架來管理依賴關係,手動約束應該是綽綽有餘的,特別是如果代碼庫的大小合理/可管理的話。不過,如果你還沒有選擇構建系統,我會推薦Bazel(儘管我有點偏頗),如果你使用它,你還可以利用其可見性限制。但是如果你已經有了一個不同的構建系統,那麼這種事情就不需要了。 –

+2

國際海事組織,他們不會建議一個「小」項目。但如果你的目標是建立一個有希望成爲一個真正的安全生產準備平臺的希望,你別無選擇,只能提出一個生產質量的解決方案。不要認爲人們還沒有嘗試......並且(客觀地)失敗。這是一個嚴重的難題。 –

相關問題