Является ли поставщик xmldsig apache santuario несовместимым с поставщиком jdk?
Я создаю цифровую подпись XML точно так же, как это упоминается почти во всех найденных мной примерах:
String providerName = System.getProperty("jsr105Provider",
"org.jcp.xml.dsig.internal.dom.XMLDSigRI");
XMLSignatureFactory fac =
XMLSignatureFactory.getInstance("DOM",
(Provider) Class.forName(providerName).newInstance());
...and so on...
Мы отправляем полученный XML-файл нашему клиенту, который проверяет эту подпись. Все тесты пройдены и до сих пор все работало нормально.
В производственной системе наш клиент неожиданно отправляет обратно "цифровая подпись неверна". После перезапуска сервера приложений все кажется снова в порядке, и некоторые файлы были успешно проверены заказчиком. Но через несколько минут / часов клиент отправляет обратно "цифровая подпись неверна". Только перезапуск сервера приложений решал проблему временно.
Я выяснил, что является причиной этой проблемы, но я не понимаю этого. Где-то в приложении используется WSS4J, инициализация выглядит следующим образом (org.apache.ws.security.WSSConfig):
public static synchronized void init() {
if (!staticallyInitialized) {
if (addJceProviders) {
setXmlSecIgnoreLineBreak();
AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
addXMLDSigRI(); <-- this line causes the problem
addJceProvider("BC", "org.bouncycastle.jce.provider.BouncyCastleProvider");
Security.removeProvider("STRTransform");
appendJceProvider(
"STRTransform", new org.apache.ws.security.transform.STRTransformProvider()
);
return true;
}
});
}
staticallyInitialized = true;
}
}
addXMLDsigRI () добавляет провайдера ApacheXMLDSig на место 2, когда его нет в текущей конфигурации провайдера (java.security). Поставщик XMLDSig jdk по умолчанию находится на месте 8.
После инициализации WSS4J каким-то образом меняется создание цифровой подписи xml, и клиент говорит, что "цифровая подпись неверна".
Я могу воспроизвести ошибку клиента, если вручную зарегистрирую провайдера ApacheXMLDSig на месте 2. Если я добавлю провайдера на место 10(после провайдера jdk), он снова заработает.
Версии:
- XML Security 1.5.6
- wss4j 1.6.10
- jdk1.7.0_13
- сервер приложений Tomcat 7
Я явно использую провайдера jdk: org.jcp.xml.dsig.internal.dom.XMLDSigRI
Почему регистрация провайдера apache "разрушает" функциональность провайдера jdk и как я могу это решить?
1 ответ
JDK регистрирует свою собственную версию поставщика безопасности xml, и при инициализации Wss4j XMLSignatureFactory берется из версии JDK, а не из jar-файла Xmlsec. В более новых версиях Wss4j это исправлено в addXMLDSigRI() следующим образом:
Security.removeProvider("ApacheXMLDSig");
addJceProvider("ApacheXMLDSig", SantuarioUtil.getSantuarioProvider());
Т.е. сначала удаляет версию провайдера, зарегистрированную JDK, затем регистрирует свою. Это предотвращает проблемы с загрузкой классов, возникающие при использовании JDK от разных поставщиков (например, Azul JDK).
Вы можете отключить регистрацию поставщика Apache Santuario в WSS4J, позвонив:
WSSConfig.setAddJceProviders (ложный);
Посмотреть здесь: