引子
在使用Fortify掃描時代碼報XML External Entity Injection,此漏洞為xml物體注入漏洞,XXE攻擊可利用在處理時動態構建檔案的 XML 功能,修復方案也包含了增加安全配置,使它不允許將外部物體包含在傳入的 XML 檔案中,
具體在修復程序中,代碼在決議drools的transfer.xls時,呼叫代碼中增加內容,包括serFeature和setAttribute
TransformerFactory factory = TransformerFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD,"");
但在執行第二行,
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
時,拋出例外
不支持:http://javax.xml.XMLConstants/property/accessExternalDTD
at org.apache.xalan.processor.TransformerFactoryImpl.setAttribute(TransformerFactoryImpl.java:571)
at XlsJava.main(XlsJava.java:10)
跟蹤與定位
仔細查看代碼,定義為javax.xml.transform.TransformerFactory的factory在setAttribute時卻進入到了路徑為org\apache\xalan\processor\TransformerFactoryImpl.class的類,
出現這個情況,因為專案中依賴了xalan的包,而在xalan包中指定了META-INF\services

因為這個設定,將完全限定名稱為javax.xml.transform.TransformerFactory類的方法映射到了路徑為
org.apache.xalan.processor.TransformerFactoryImpl
的類上,而在此類中經過一系列判斷最終拋出例外

解決方案
解決這個問題的方法也很簡單,只需要在呼叫此段代碼的工程之下,覆寫xalan包的設定即可,具體實作為,在呼叫
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
的工程下配置META-INF/services路徑,新建名稱為
javax.xml.transform.TransformerFactory
的檔案,其檔案內容為
com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
如圖

SPI機制
SPI是Service Provider Interface 的簡稱,即服務提供者介面的意思,上文所使用的處理方法就是SPI機制的實體,SPI自jdk1.6開始引入,此后便有了廣泛的應用,最常見的就是資料庫連接,JDK提供了一個java.sql.Driver介面,根據不同的資料庫廠商來引入不同的JDBC驅動包,比如MySQL這些資料庫驅動其實都會實作這個驅動類,SPI機制要求拓展內容需存放在resources/META-INF/services目錄下,META-INF用于存盤服務提供者(service provider)的組態檔,serviceloader從META-INF/services中檔案查找service的實作,該檔案具有與service介面相同的限定名,其內容包括實作的限定名串列,如此,serviceloader將呼叫META-INF/services中檔案的具體實作,所以,
javax.xml.transform.TransformerFactory
類的實作,卻在呼叫方法的時候定位到了
org.apache.xalan.processor.TransformerFactoryImpl
為什么必須是META-INF/services之下?看了原始碼你可能就會明白
public final class ServiceLoader<S> implements Iterable<S>{
private static final String PREFIX = "META-INF/services/";
}
SPI機制的優缺點
優點
- 其核心思想就是解耦,讓介面和實作分離開來
- 提高框架的擴展性,可以使框架根據實際業務情況啟用擴展或替換框架組件
缺點
- serviceloader對實作類的加載使用的是懶加載,在使用回圈遍歷時,即使是不必要加載的類同樣會被實體化,造成浪費
- serviceloader不是執行緒安全的
更多的關于SPI的相關內容,參考官方檔案https://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/502211.html
標籤:其他
上一篇:騰訊三面:行程寫檔案程序中,行程崩潰了,檔案資料會丟嗎?
下一篇:字串格式化
