針對因accessExternalDTD
屬性限制導(dǎo)致無法通過HTTP訪問外部DTD(如MyBatis的mybatis-3-mapper.dtd
)的問題,以下是詳細的解決方案:
Java XML解析器默認禁止從外部加載DTD(防止XXE攻擊),因此當(dāng)XML文件嘗試通過HTTP訪問遠程DTD(如<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">)時,會拋出以下錯誤:
org.xml.sax.SAXParseException: 外部 DTD: 無法讀取外部 DTD 'mybatis-3-mapper.dtd', 因為 accessExternalDTD 屬性設(shè)置的限制導(dǎo)致不允許 'http' 訪問
根據(jù)需求選擇以下任意一種方法:
在創(chuàng)建DocumentBuilder
或SAXParser
時,顯式允許訪問HTTP協(xié)議的DTD:
import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; public class XmlParser { public static void main(String[] args) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 關(guān)鍵配置:允許通過HTTP訪問外部DTD factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "http"); DocumentBuilder builder = factory.newDocumentBuilder(); builder.parse("input.xml"); // 解析XML文件 } catch (ParserConfigurationException | SAXException | IOException e) { e.printStackTrace(); } } }
在啟動應(yīng)用時添加以下參數(shù),允許所有XML解析器訪問HTTP/HTTPS協(xié)議的外部DTD:
java -Djavax.xml.accessExternalDTD=http,https -jar YourApp.jar
避免依賴遠程DTD,將mybatis-3-mapper.dtd
下載到本地,并修改XML的DOCTYPE聲明指向本地路徑:
下載DTD文件
訪問 http://mybatis.org/dtd/mybatis-3-mapper.dtd 并將文件保存到項目目錄(如src/main/resources/dtd/mybatis-3-mapper.dtd
)。
修改XML聲明
將XML中的DOCTYPE路徑替換為本地路徑:
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "classpath:/dtd/mybatis-3-mapper.dtd">
如果無需DTD驗證,可直接禁用外部實體解析:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); // 啟用安全處理 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // 禁用DOCTYPE
安全風(fēng)險
允許外部DTD訪問可能引發(fā)XXE攻擊,確保僅加載可信來源的DTD。
兼容性
部分舊版XML解析器(如Apache Xerces 1.x)可能不支持ACCESS_EXTERNAL_DTD
屬性,建議升級到較新版本。
MyBatis框架集成
若在MyBatis中遇到此問題,建議優(yōu)先使用本地DTD文件,避免因網(wǎng)絡(luò)問題導(dǎo)致解析失敗。
這里建議使用第三種方法,比較簡單,也安全可靠!