專利名稱:一種在Java虛擬機(jī)中安全運(yùn)行第三方代碼的方法
技術(shù)領(lǐng)域:
本發(fā)明涉及信息安全領(lǐng)域,特別涉及一種安全運(yùn)行不可控的第三方代碼的方法。
背景技術(shù):
軟件或服務(wù)器往往需要允許用戶執(zhí)行自定義的代碼以實(shí)現(xiàn)高度的可定制性或安全性。但是由于第三方編寫的代碼的不可控性,限制其運(yùn)行環(huán)境以保護(hù)服務(wù)器資源或上層軟件的正常運(yùn)行就成了一個(gè)很重要的問題。JVM是Java Virtual Machine (Java虛擬機(jī))的縮寫,JVM是一種用于計(jì)算設(shè)備的規(guī)范,它是一個(gè)虛構(gòu)出來的計(jì)算機(jī),是通過在實(shí)際的計(jì)算機(jī)上仿真模擬各種計(jì)算機(jī)功能來實(shí)現(xiàn)的。JVM屏蔽了與具體操作系統(tǒng)平臺(tái)相關(guān)的信息,使Java程序只需生成在Java虛擬機(jī)上運(yùn)行的目標(biāo)代碼(字節(jié)碼),就可以在多種平臺(tái)上不加修改地運(yùn)行。JVM在執(zhí)行字節(jié)碼·時(shí),實(shí)際上最終還是把字節(jié)碼解釋成具體平臺(tái)上的機(jī)器指令執(zhí)行。在JVM中使用一個(gè)類時(shí),該類的加載過程是唯一可以在外部進(jìn)行干預(yù)的,這可以通過JVM提供的自定義類加載器來實(shí)現(xiàn)。通常JVM中引入自定義類加載器的主要目的是實(shí)現(xiàn)代碼的熱部署,如OSGi系統(tǒng)等。OSGi (Open Service Gateway Initiative)技術(shù)是面向Java的動(dòng)態(tài)模型系統(tǒng)。OSGi服務(wù)平臺(tái)向Java提供服務(wù),這些服務(wù)使Java成為軟件集成和軟件開發(fā)的首選環(huán)境。OSGi技術(shù)提供允許應(yīng)用程序使用精煉、可重用和可協(xié)作的組件構(gòu)建的標(biāo)準(zhǔn)化原語。這些組件能夠組裝進(jìn)一個(gè)應(yīng)用和部署中。JVM虛擬機(jī)提供的安全性主要通過虛擬機(jī)的安全策略文件實(shí)現(xiàn),通過安全策略文件控制JVM中類對(duì)資源的訪問(如文件系統(tǒng)和網(wǎng)絡(luò)資源等)。但是在實(shí)際應(yīng)用中,往往需要控制第三方代碼本身不能直接訪問一些外部資源(如文件、網(wǎng)絡(luò)和一些本地模塊的加載等),但是可以通過調(diào)用本地提供的方法來訪問,而且JVM同時(shí)運(yùn)行多個(gè)不同的第三方代碼時(shí)還要實(shí)現(xiàn)代碼間的相互隔離,這時(shí)只通過在JVM啟動(dòng)時(shí)靜態(tài)地提供一個(gè)安全策略文件很難實(shí)現(xiàn)。
發(fā)明內(nèi)容
有鑒于此,本發(fā)明提供了一種在JVM上安全運(yùn)行第三方代碼的方法,利用JVM提供的自定義類加載器的技術(shù)來控制第三方代碼的本地模塊和類的加載,只允許第三方代碼加載和使用系統(tǒng)提供的已封裝好業(yè)務(wù)邏輯的類,第三方代碼對(duì)外部資源的訪問只能通過上述系統(tǒng)提供的已封裝好的業(yè)務(wù)邏輯類的接口執(zhí)行,第三方代碼本身不能直接訪問外部資源,從而實(shí)現(xiàn)安全訪問外部資源。根據(jù)本發(fā)明,提供一種在Java虛擬機(jī)中安全運(yùn)行第三方類的方法,該方法包括 創(chuàng)建自定義加載器,所述自定義加載器的父加載器為Java虛擬機(jī)當(dāng)前線程的類加載
器;
通過所述自定義加載器來加載第三方類,由所述自定義加載器判斷是否允許所述第三方類加載特定的系統(tǒng)類;如果允許,則所述自定義加載器委托其父加載器加載所述系統(tǒng)類;
若不允許,則拋出異常,從而控制所述第三方類中所能使用的類。根據(jù)本發(fā)明的一個(gè)方面,根據(jù)需要,能夠同時(shí)創(chuàng)建多個(gè)所述自定義加載器以執(zhí)行多份所述第三方類。根據(jù)本發(fā)明的一個(gè)方面 ,關(guān)于所述第三方類所允許訪問的類和/或所不允許訪問的類的信息存放在所述自定義類加載器能夠找到的存放位置。根據(jù)本發(fā)明的一個(gè)方面,所述信息存放在特定文件中,或所述信息存放在數(shù)據(jù)庫中,或所述信息直接寫入在程序代碼中。根據(jù)本發(fā)明的一個(gè)方面,所述自定義類加載器加載所述第三方類時(shí),確定所述第三方類可使用和/或不可使用的類。根據(jù)本發(fā)明的一個(gè)方面,如果所述自定義加載器判斷出所述第三方類加載不允許加載的類時(shí),拋出異常。根據(jù)本發(fā)明的一個(gè)方面,分別采用不同的加載器來分別加載所述第三方類以防止惡意訪問。
圖I為按照本發(fā)明的一種在JVM上安全運(yùn)行第三方代碼的方法的一優(yōu)選實(shí)施例的流程示意圖。圖2為圖I所示實(shí)施例中結(jié)構(gòu)框圖。
具體實(shí)施例方式當(dāng)JVM需要加載第三方代碼時(shí),創(chuàng)建一個(gè)自定義的類加載器,其父加載器設(shè)置為JVM當(dāng)前線程的默認(rèn)類加載器(根據(jù)本發(fā)明的一個(gè)實(shí)施例,通常就是SystemClassLoader),通過自定義類加載器的一個(gè)實(shí)例來加載第三方代碼。在自定義類加載器中通過一個(gè)可使用類的列表(或不可使用類的列表)來控制第三方代碼中外部類的使用,自定義類加載器的功能如下
1、對(duì)于允許使用的本地模塊中的類(如java.lang. String等,所有的java類都要繼承java. lang. Object類,下面不再贅述),直接委托其父加載器(SystemClassLoader)執(zhí)行,這也是JVM類加載器的默認(rèn)行為,由此第三方代碼可以正常使用這些類;
2、對(duì)于不允許使用的本地模塊中的類(如java.net. *和java. io. *等),自定義類加載器將直接拋出ClassNotFound異常;
3、需要訪問外部資源的業(yè)務(wù)邏輯封裝于單獨(dú)的功能類中(下文稱為Function類),自定義類加載器將直接由其父加載器加載Function類,由此Function類中再加載使用其它類時(shí)(如java. net. *等限制第三方代碼使用的類)將直接使用父加載器,從而安全地繞過自定義類加載器的限制。如此便可以實(shí)現(xiàn)第三方代碼本身只能使用允許的類,可以輕易地?cái)嘟^其訪問外部資源(此處指所有不允許訪問的資源包含虛擬機(jī)自身內(nèi)存等)的途徑,同時(shí)可以通過Function類提供的高級(jí)接口以可控的方式訪問外部資源。通常JVM提供的非訪問外部資源的類可以由第三方代碼安全調(diào)用,如java. lang.String以及java. math模塊中的等大部分的類都是如此。對(duì)待這些類的加載,根據(jù)本發(fā)明的一個(gè)是實(shí)施例,自定義的類加載器MyClassLoader的行為即是JVM類加載器的默認(rèn)行為,即雙親代理模式(即,優(yōu)先委托自己的父加載器加載,父加載器不能加載時(shí)才自己加載。)。而對(duì)于java. io、java. net以及java. thread等模塊中的類,自定義類加載器將會(huì)打破JVM的默認(rèn)行為,從而拒絕加載這些類;自定義類加載器正常(委托其父加載器)加載Function類后,F(xiàn)unction類便屬于自定義類加載器的父加載器,所以Function類中的類加載將由自定義類加載器的父加載器負(fù)責(zé),從而可以在Function中實(shí)現(xiàn)訪問外部資源實(shí)現(xiàn)業(yè)務(wù)邏輯,F(xiàn)unction代碼由功能提供者實(shí)現(xiàn),是可控的,而第三方代碼只能通過這一條途徑來訪問外部資源,因此也是可控的。自定義類加載器中的允許或不允許加載的類列表可以是預(yù)置的,所有的第三方類代碼使用相同的配置;也可以是加載不同的第三方類代碼時(shí)現(xiàn)讀取的,每個(gè)類有不同的權(quán)限,由此在JVM中實(shí)現(xiàn)動(dòng)態(tài)的代碼權(quán)限控制。在JVM中,通過類加載器和類名才能確定一個(gè)類,對(duì)于不同的第三方代碼,都創(chuàng)建
一個(gè)新的自定義類加載器實(shí)例來加載。由于第三方代碼加載時(shí)需要不同的類加載器,所以第三方代碼之間無法相互訪問,從而實(shí)現(xiàn)了不同第三方代碼之間的隔離。當(dāng)所執(zhí)行的第三方代碼之間不需要隔離時(shí)(如是同一個(gè)用戶的代碼),則可以使用同一個(gè)類加載器加載,從而節(jié)省系統(tǒng)資源。 上述自定義類加載器通常可以通過重載ClassLoader類的f indClass和IoadClass方法即可實(shí)現(xiàn),此為Java中的標(biāo)準(zhǔn)方法,本發(fā)明中不再贅述。
為使本發(fā)明的目的、技術(shù)方案及優(yōu)點(diǎn)更加清楚明白,以下結(jié)合附圖描述本發(fā)明的優(yōu)選實(shí)施例,對(duì)本發(fā)明進(jìn)一步詳細(xì)說明。如圖I所示,本發(fā)明中自定義類加載器加載一個(gè)類包括如下步驟其中,在該類的實(shí)例創(chuàng)建時(shí)已經(jīng)獲得了哪些類可加載而哪些類不可加載的信息,在圖I中已經(jīng)略去)
步驟I :開始執(zhí)行;
步驟2:判斷是否允許加載該類;如果允許加載該類,則進(jìn)入步驟3,否則拋出ClassNotFound 異常;
步驟3 :判斷加載的類是否是要限制使用的第三方類,如果是,則進(jìn)入步驟4 ;如果不是,則進(jìn)入步驟5;
步驟4 :從字節(jié)碼直接加載第三方類;
步驟5 :委托父加載器加載第三方類;
步驟6:結(jié)束加載過程。圖2給出了實(shí)現(xiàn)本發(fā)明的結(jié)構(gòu)示意圖。圖2虛線框中為第三方代碼運(yùn)行環(huán)境,該環(huán)境運(yùn)行在JVM中。其中包括第三方類代碼本身和訪問外部資源的業(yè)務(wù)邏輯封裝類。第三方類代碼需要通過自定義類加載器才能被系統(tǒng)類加載器所加載,而訪問外部資源的業(yè)務(wù)邏輯封裝類則直接由系統(tǒng)類加載器加載。其中,第三方類代碼在未加載到JVM前是文本形式的代碼,而加載到JVM中之后是
一個(gè)類。。
實(shí)施例I
該實(shí)施例中需要加載的第三方類是ThirdExample。第三方類ThirdExample的字節(jié)碼存在ThirdExample. class文件中,只允許直接使用java. lang. String類和默認(rèn)的java.lang. Object類。而ThirdExample類只允許直接使用java. lang. String類的信息則存放在ThirdExampleAccess. txt這個(gè)文本文件中。在ThirdExample類中需要訪問外部資源/tmp/example, db文件。該功能通過類example. FileAccessffrapper提供的公共方法(read和write,即讀寫功能)實(shí)現(xiàn),而example. FileAccessffrapper是系統(tǒng)提供者提供的訪問外部資源的封裝類,該封裝類根據(jù)系統(tǒng)的安全需求以及業(yè)務(wù)邏輯編寫。在本例中example.FileAccessWrapper通過使用java. io. *等在ThirdExample中不能使用的類來實(shí)現(xiàn)文件操作,同時(shí)該類只能訪問/tmp/example. db文件,從而防止了 ThirdExample對(duì)其它資源的訪問。其中ThirdExampleAccess. txt文件的內(nèi)容描述相應(yīng)第三方代碼可以加載的類, 形式可以根據(jù)需求進(jìn)行選擇,如其中記錄可以加載的類,或只記錄不可以加載的類,或兩者者[H己錄等等。通過ThirdExample. class可以確定其對(duì)應(yīng)的權(quán)限文件的位置,如本例中可以通過文件名來找到ThirdExampleAccess. txt文件。ThirdExample類由自定義的類加載器MyClassLoader加載,本例中MyClassLoader的工作流程如下
1、創(chuàng)建MyClassLoader,以當(dāng)前線程的加載器作為其父加載器;
2、若加載ThirdExample類,則從ThirdExample.class中讀取類字節(jié)碼,然后加載;同時(shí)讀取對(duì)應(yīng)的ThirdExampleAccess. txt,確定ThirdExample可使用類的列表(或不可加載類的列表);3、加載(都是從類ThirdExample中)其它類時(shí),若ThirdExampleAccess. txt中允許加載,則委托其父加載器加載,否則拋出ClassNotFound異常;
本例中只有 java. lang. String 和 example. FileAccessWrapper 可以加載,在ThirdExample所有加載其它類的操作均會(huì)拋出ClassNotFound異常,從而使得ThridExample沒有途徑直接訪問外部資源,example. FileAccessffrapper提供了訪問外部資源途徑的同時(shí)也隱藏了相關(guān)細(xì)節(jié)。4、當(dāng)ThirdExample類執(zhí)行完畢后,MyClassLoader便不再使用(可被回收)。此外,根據(jù)本實(shí)施例,可以根據(jù)需要同時(shí)創(chuàng)建多個(gè)MyClassLoader以執(zhí)行多份ThirdExample代碼,這些MyClassLoader之間的執(zhí)行過程互不影響。
實(shí)施例2
同上例,只是控制第三方類中可訪問的資源不同。第三方類代碼ThirdExample.class (存在文件中)允許直接使用除java. net. *以外的所有類,此信息放在ThirdExampleAccess. txt這個(gè)文本文件。外部需要通過網(wǎng)絡(luò)訪問TCP的80端口。該功能通過類 example. NetAccessffrapper 提供的公共方法(open、send、recieve 和 close,即打開、發(fā)送、接收和關(guān)閉功能)實(shí)現(xiàn),example. NetAccessffrapper隱藏為網(wǎng)絡(luò)訪問的細(xì)節(jié)(如協(xié)議、端口和底層實(shí)現(xiàn)等)。example. NetAccessffrapper是系統(tǒng)提供者提供的訪問外部資源的封裝類,根據(jù)系統(tǒng)的安全需求以及業(yè)務(wù)邏輯編寫。在本例中example. NetAccessffrapper通過使用java. net. *等在ThirdExample中不能使用的類來實(shí)現(xiàn)文件操作,同時(shí)該類只能訪問TCP的80端口,從而防止了 ThirdExample對(duì)其它網(wǎng)絡(luò)資源的訪問。自定義的類加載器MyClassLoader工作流程如下
1、創(chuàng)建MyClassLoader,以當(dāng)前線程的加載器作為其父加載器;
2、若加載ThirdExample類,則從ThirdExample. class中讀取類字節(jié)碼,然后加載;同時(shí)讀取對(duì)應(yīng)的ThirdExampleAccess. txt,確定ThirdExample可使用類的列表(或不可加載類的列表);
3、加載(都是從類ThirdExample中加載)其它類時(shí),若ThirdExampleAccess.txt中允許加載,貝U委托其父加載器加載,否則拋出ClassNotFound異常;本例中除java.net. *以外的所有類都可以加載,在ThirdExample所有加載任何java. net. *類的操作均會(huì)拋出ClassNotFound異常,從而使得ThridExample沒有途徑直接訪問網(wǎng)絡(luò),example.NetAccessffrapper提供了訪問外部資源途徑的同時(shí)也隱藏了相關(guān)細(xì)節(jié)。 4、當(dāng)ThirdExample類執(zhí)行完畢后,MyClassLoader便不再使用(可被回收)。此夕卜,根據(jù)本實(shí)施例,可以根據(jù)需要同時(shí)創(chuàng)建多個(gè)MyClassLoader以執(zhí)行多份ThirdExample代碼,這些MyClassLoader之間的執(zhí)行過程互不影響。
實(shí)施例3
此外,根據(jù)本發(fā)明的一個(gè)具體實(shí)施方式
,除了上述兩個(gè)具體實(shí)施例中通過讀取ThirdExampleAccess. txt,從而確定ThirdExample可使用類的列表(或不可加載類的列表)的方式之外,本領(lǐng)域的技術(shù)人員完全可以采用其它的方式來確定所述第三方類所允許訪問的類和/或所不允許訪問的類的信息,其中一種具體的方式就是將所述信息存放在數(shù)據(jù)庫中,或所述信息直接寫入在程序代碼中。這種變化對(duì)于本領(lǐng)域技術(shù)人員而言是容易實(shí)現(xiàn)的,其相應(yīng)的后續(xù)步驟與上述實(shí)施例1、2的后續(xù)步驟類似,不再贅述。
以上所述僅為本發(fā)明的較佳實(shí)施例而已,并非用于限定本發(fā)明的保護(hù)范圍。凡在本發(fā)明的精神和原則之內(nèi),所作的任何修改、等同替換以及改進(jìn)等,均應(yīng)包含在本發(fā)明的保護(hù)范圍之內(nèi)。
權(quán)利要求
1.一種在Java虛擬機(jī)中安全運(yùn)行第三方類的方法,其特征在于,該方法包括 創(chuàng)建自定義加載器,所述自定義加載器的父加載器為Java虛擬機(jī)當(dāng)前線程的類加載器; 通過所述自定義加載器來加載第三方類,由所述自定義加載器判斷是否允許所述第三方類加載特定的系統(tǒng)類; 如果允許,則所述自定義加載器委托其父加載器加載所述系統(tǒng)類; 若不允許,則拋出異常,從而控制所述第三方類中所能使用的類。
2.根據(jù)權(quán)利要求I所述的方法,其特征在于,根據(jù)需要,能夠同時(shí)創(chuàng)建多個(gè)所述自定義加載器以執(zhí)行多份所述第三方類。
3.根據(jù)權(quán)利要求I所述的方法,其特征在于,關(guān)于所述第三方類所允許訪問的類和/或所 不允許訪問的類的信息存放在所述自定義類加載器能夠找到的存放位置。
4.根據(jù)權(quán)利要求3所述的方法,其特征在于,所述信息存放在特定文件中,或所述信息存放在數(shù)據(jù)庫中,或所述信息直接寫入在程序代碼中。
5.根據(jù)權(quán)利要求2所述的方法,其特征在于,所述自定義類加載器加載所述第三方類時(shí),確定所述第三方類可使用和/或不可使用的類。
6.根據(jù)權(quán)利要求1-5所述的方法,其特征在于,如果所述自定義加載器判斷出所述第三方類加載不允許加載的類時(shí),拋出異常。
7.根據(jù)權(quán)利要求2所述的方法,其特征在于,分別采用不同的加載器來分別加載所述第三方類以防止惡意訪問。
全文摘要
本發(fā)明公開了一種利用JVM提供的自定義類加載器的技術(shù)實(shí)現(xiàn)安全運(yùn)行不可控的第三方代碼的方法。通過控制第三方代碼中可以使用的本地模塊和類,可以有效限制其對(duì)外部資源的訪問,同時(shí)也可以隔離多個(gè)同時(shí)運(yùn)行的第三方代碼。本發(fā)明也提供了在第三方代碼中以可控的方式透明訪問本地資源的方法。
文檔編號(hào)G06F9/445GK102902911SQ20121034476
公開日2013年1月30日 申請(qǐng)日期2012年9月18日 優(yōu)先權(quán)日2012年9月18日
發(fā)明者不公告發(fā)明人 申請(qǐng)人:北京深思洛克軟件技術(shù)股份有限公司