Я видел несколько вопросов по настройке безопасности wsit
, большинство из которых касаются экстернализации конфигурации SSL, а не жесткого кодирования в файл wsdl. Просто потому, что может быть среда разработки и производства, и все в жестко заданной конфигурации в любом случае плохо. Я провел несколько дней с этой проблемой и нашел только некоторые (часто чудовищные) подсказки здесь в stackoverflow и различных других форумах. Но решение оказалось не таким уж сложным. Я просто оставляю это здесь для кого-то (это соответствует также оригинальному вопросу, потому что это позволит иметь jks где угодно, также имея внешний файл конфигурации).
Скажем, у вас есть политика wsit в ваших wsdl-файлах:
<wsp1:Policy wsu:Id="MyBinding_IWebServicePolicy">
<wsp1:ExactlyOne>
<wsp1:All>
<sc:KeyStore wspp:visibility="private" type="JKS" storepass="pass" alias="some-alias" keypass="pass" location="keystore.jks"/>
<sc:TrustStore wspp:visibility="private" type="JKS" peeralias="other-alias" storepass="pass" location="truststore.jks"/>
</wsp1:All>
</wsp1:ExactlyOne>
</wsp1:Policy>
Вам нужно использовать CallbackHandler
вместо.
Скорректированная политика:
<wsp1:Policy wsu:Id="MyBinding_IWebServicePolicy">
<wsp1:ExactlyOne>
<wsp1:All>
<sc:KeyStore wspp:visibility="private" callbackHandler="com.my.KeyStoreHandler"/>
<sc:TrustStore wspp:visibility="private" callbackHandler="com.my.TrustStoreHandler"/>
</wsp1:All>
</wsp1:ExactlyOne>
</wsp1:Policy>
И обработчик может выглядеть так (я использую scala, но вы можете легко перевести это на java):
import javax.security.auth.callback.{ CallbackHandler => ICallbackHandler, Callback }
import com.sun.xml.wss.impl.callback.{ KeyStoreCallback, PrivateKeyCallback }
import java.security.{ PrivateKey, KeyStore }
import java.io.FileInputStream
abstract class CallbackHandler extends ICallbackHandler {
def conf: Config // getting external configuration
def handle(callbacks: Array[Callback]): Unit = callbacks foreach {
// loads the keystore
case cb: KeyStoreCallback =>
val ks = KeyStore.getInstance(conf.getString("type"))
val is = new FileInputStream(conf.getString("file"))
try ks.load(is, conf.getString("store-password").toCharArray) finally is.close()
cb.setKeystore(ks)
// loads private key
case cb: PrivateKeyCallback =>
cb.setAlias(conf.getString("alias"))
cb.setKey(cb.getKeystore.getKey(conf.getString("alias"), conf.getString("key-password").toCharArray).asInstanceOf[PrivateKey])
// other things
case cb => // I didn't need anything else, but just in case
}
}
class TrustStoreHandler extends CallbackHandler {
lazy val conf = getMyTrustStoreConfig
}
class KeyStoreHandler extends CallbackHandler {
lazy val conf = getMyKeyStoreConfig
}
В Java просто используйте if (cb isinstanceof Class)
вместо case cb: Class =>
, другой код - практически Java без точек с запятой.