I have written a java code using Jdeveloper tool to call external web service. When I am running my code from Jdeveloper it is working fine. But I am deploying my code on Oracle weblogic 10.3.6 server and try to run this code then It is giving me below error -
javax.xml.soap.SOAPException: Content-Type not specified
Here is my code -
public static String callTestService(String soapRequestXml, String url) {
try{
final boolean isHttps = url.toLowerCase().startsWith("https");
HttpsURLConnection httpsConnection = null;
// Open HTTPS connection
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
if (isHttps) {
// Create SSL context and trust all certificates
SSLContext sslContext = SSLContext.getInstance("SSL");
//TrustManager[] trustAll= new TrustManager[] {new TrustAllCertificates()};
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Set trust all certificates context to HttpsURLConnection
HttpsURLConnection
.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
// Open HTTPS connection
// URL url1 = new URL(url);
URL url1 = new URL(null, url, new sun.net.www.protocol.https.Handler());
httpsConnection = (HttpsURLConnection) url1.openConnection();
// Trust all hosts
// httpsConnection.setHostnameVerifier(new TrustAllHosts());
// Connect
//Use below (2 lines) if Host name verification needs to turned off
MyHostnameVerifier HostVerifier = new MyHostnameVerifier();
httpsConnection.setHostnameVerifier(HostVerifier);
httpsConnection.connect();
}
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
System.out.println("create connection");
// SOAPMessage soapRequest = MessageFactory.newInstance().createMessage(new MimeHeaders(),
// new ByteArrayInputStream(soapRequestXml.getBytes()));
SOAPMessage soapRequest = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL).createMessage(new MimeHeaders() ,
new ByteArrayInputStream(soapRequestXml.getBytes(Charset.forName("UTF-8"))));
// SOAPMessage s = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
// SOAPPart soapPart = soapRequest.getSOAPPart();
// SOAP Envelope
// SOAPEnvelope envelope = soapPart.getEnvelope();
// envelope.addNamespaceDeclaration("Dokumentai", "http://vmi.lt/ais/xsd/daa");
// MessageFactory messageFactory = MessageFactory.newInstance();
//SOAPMessage soapRequest = messageFactory.createMessage(new MimeHeaders(),soapRequestXml);
// MessageFactory messageFactory = MessageFactory.newInstance();
// SOAPMessage soapRequest = messageFactory.createMessage();
// SOAPPart soapPart = soapRequest.getSOAPPart();
// SOAPEnvelope envelope = soapPart.getEnvelope();
// SOAPBody soapBody = envelope.getBody();
//soapBody.setTextContent(soapRequestXml);
// soapRequest.setContentDescription(soapRequestXml);
// SOAPPart soapPart = soapRequest.getSOAPPart();
//SOAPEnvelope envelope = soapPart.getEnvelope();
// String serverURI = "myhost";
// envelope.addNamespaceDeclaration("xmlns",
// "http://vmi.lt/ais/xsd/daa");
// SOAP Envelope
// SOAPEnvelope envelope = soapPart.setContent(soapRequestXml);
// System.out.println("SOAP "+ soapRequest.writeTo(System.out));
MimeHeaders headers = soapRequest.getMimeHeaders();
headers.setHeader("SOAPAction",
"http://vmi.lt/ais/ws/handleMessage");
MimeHeaders headers1 = soapRequest.getMimeHeaders();
headers1.setHeader("Content-Type", "application/soap+xml; charset=utf-8");
soapRequest.saveChanges();
soapRequest.writeTo(System.out);
System.out.println("call request url");
// Send SOAP Message to SOAP Server
SOAPMessage soapResponse = soapConnection.call(soapRequest, url);
soapResponse.setProperty("Content-Type", "application/xml; charset=utf-8");
soapResponse.setContentDescription("application/xml; charset=utf-8");
ByteArrayOutputStream soapResponseBaos = new ByteArrayOutputStream();
soapResponse.writeTo(soapResponseBaos);
String soapResponseXml = soapResponseBaos.toString();
return soapResponseXml;
}catch(Exception e){
return e.toString();
}
}
I have tried many different things but it works fine when i call web service directly from Jdeveloper but fails when I call from Oracle web logic server.
Could you please help me with this?
I have fixed this issue.Please make following changes in the code.
MimeHeaders headers1 = new MimeHeaders();
headers1.setHeader("Content-Type", "text/xml");
headers1.setHeader("Encoding", "UTF-8");
// SOAPMessage soapRequest =
// MessageFactory.newInstance().createMessage(new MimeHeaders(),
// new ByteArrayInputStream(soapRequestXml.getBytes(Charset.forName("UTF-8"))));
SOAPMessage soapRequest = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL).createMessage(headers1 ,
new ByteArrayInputStream(soapRequestXml.getBytes(Charset.forName("UTF-8"))));
I have a wsdl from ERP cloud. To consume it in Java, I compiled it using wsimport and extracted all the java files.
Now I'm trying to use these java files in order to communicate to the server data through wsdl. The wsdl requires authentication.
Problem
Whenever I try to run my custom code to connect to wsdl, for authentication it works with simple setting of username and password in Binding context.
private void attachAuthentication(Object className) {
BindingProvider prov = (BindingProvider) className;
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "xxx");
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "xxx");
}
But whenever I deploy my code on a weblogic GPI instance, it gives me following error.
com.sun.xml.ws.fault.ServerSOAPFaultException: Client received SOAP Fault from server: The request was invalid or malformed Please see the server log to find more detail regarding exact cause of the failure.
at com.sun.xml.ws.fault.SOAP12Fault.getProtocolException(SOAP12Fault.java:229)
at com.sun.xml.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:139)
at com.sun.xml.ws.client.sei.StubHandler.readResponse(StubHandler.java:253)
at com.sun.xml.ws.db.DatabindingImpl.deserializeResponse(DatabindingImpl.java:203)
at com.sun.xml.ws.db.DatabindingImpl.deserializeResponse(DatabindingImpl.java:290)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:119)
I tried attaching a Soap handler to my SEI. Here's what I've done.
InitializeErp.java
HeaderHandlerResolver handlerResolver = new HeaderHandlerResolver();
InvoiceInterfaceService_Service interfaceInvoice = new InvoiceInterfaceService_Service();
interfaceInvoice.setHandlerResolver(handlerResolver);
invoiceInterfaceServiceSoapHttpPort = interfaceInvoice.getInvoiceInterfaceServiceSoapHttpPort();
HeaderHandlerResolver.java
public class HeaderHandlerResolver implements HandlerResolver {
#Override
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerChain = new ArrayList<Handler>();
HandlerHeader hh = new HandlerHeader();
handlerChain.add(hh);
return handlerChain;
}
}
HeaderHandler.java
public class HandlerHeader implements SOAPHandler<SOAPMessageContext> {
#Override
public Set<QName> getHeaders() {
return Collections.emptySet();
}
#Override
public boolean handleMessage(SOAPMessageContext context) {
final Boolean outInd = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outInd) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.mmm'Z'");
Date creationDate = new Date();
Date expirationDate = new Date(creationDate.getTime() + TimeUnit.HOURS.toMillis(1));
try {
SOAPMessage message = context.getMessage();
SOAPEnvelope env = message.getSOAPPart().getEnvelope();
env.addNamespaceDeclaration("sch", "http://xmlns.oracle.com/scheduler");
env.addNamespaceDeclaration("typ", "http://xmlns.oracle.com/scheduler/types");
SOAPHeader header = env.getHeader();
SOAPBody body = env.getBody();
env.removeNamespaceDeclaration("SOAP-ENV");
env.setPrefix("soapenv");
header.setPrefix("soapenv");
body.setPrefix("soapenv");
QName security = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security", "wsse");
// Constructing Header
SOAPElement securityElement = header.addChildElement(security);
securityElement.addNamespaceDeclaration("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
securityElement.setAttribute("soapenv:mustUnderstand", "1");
QName usernameToken = new QName("UsernameToken", "wsse");
SOAPElement usernameTokenElement = securityElement.addChildElement("UsernameToken", "wsse");
usernameTokenElement.setAttribute("wsu:Id", "UsernameToken-97B1FF404874F4997215144527824364");
QName username = new QName("Username", "wsse");
SOAPElement usernameElement = usernameTokenElement.addChildElement("Username", "wsse");
usernameElement.addTextNode("xxx");
QName passwrod = new QName("Password", "wsse");
SOAPElement passwordElement = usernameTokenElement.addChildElement("Password", "wsse");
passwordElement.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
passwordElement.addTextNode("xxx");
QName nonce = new QName("Nonce", "wsse");
SOAPElement nonceElement = usernameTokenElement.addChildElement("Nonce", "wsse");
nonceElement.setAttribute("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
nonceElement.addTextNode("Ox0BI3sh1pPSe2S7NsUzeg==");
QName created = new QName("Created", "wsu");
SOAPElement createdElement = usernameTokenElement.addChildElement("Created", "wsu");
createdElement.addTextNode(format.format(creationDate));
QName timestamp = new QName("Timestamp", "wsu");
SOAPElement timestampElement = securityElement.addChildElement("Timestamp", "wsu");
timestampElement.setAttribute("wsu:Id", "TS-4");
QName createdTimestamp = new QName("Created", "wsu");
SOAPElement createdTimestampElement = timestampElement.addChildElement("Created", "wsu");
createdTimestampElement.addTextNode(format.format(creationDate));
QName expiresTimestamp = new QName("Expires", "wsu");
SOAPElement expiresTimestampElement = timestampElement.addChildElement("Expires", "wsu");
expiresTimestampElement.addTextNode(format.format(expirationDate));
// Print out the outbound SOAP message to System.out
System.out.println("setting attributes...");
message.writeTo(System.out);
System.out.println("");
System.out.println("message printed..");
} catch (Exception e) {
e.printStackTrace();
}
}
return true;
}
#Override
public boolean handleFault(SOAPMessageContext context) {
try {
SOAPMessage message = context.getMessage();
ByteArrayOutputStream out = new ByteArrayOutputStream();
message.writeTo(out);
String strMsg = new String(out.toByteArray());
RequestFilter.getSession().setAttribute("soap fault", "Soap ->" + strMsg);
} catch (SOAPException | IOException ex) {
RequestFilter.getSession().setAttribute("mailContent", ex.toString());
}
return true;
}
#Override
public void close(MessageContext context) {
}
}
This is what my Soap HEader looks like.
On running it on server. This is what I get in my SoapFault
Soap -> ns1:Senderns2:InvalidRequestThe request was invalid or malformedweblogic.wsee.security.wst.faults.InvalidRequestException: Server Authentication Required at weblogic.wsee.security.wst.framework.TrustSoapClient.invoke(TrustSoapClient.java:157) at weblogic.wsee.security.wst.framework.TrustSoapClient.requestTrustToken(TrustSoapClient.java:110) at weblogic.wsee.security.saml.SAMLTrustCredentialProvider.createCredential(SAMLTrustCredentialProvider.java:432) at
I've many ways to modify the Soap header, Removed security, just passed username password, Added both handler as well as credentials in BindingContext, But nothing seems to work on server.
With the header attached, I get the following error on local
I'm out of ways now. Can anyone please suggest me any approach or point out what am I missing. What should I try now. Any help is appreciated. All suggestions are welcome.
I am experiencing a problem while trying to send a soap request on a https server.
I seems that I am not sending any certificate but I don't know how to do that. I get an SSL handshake error.
Here is my source code. Sorry for the mess .... :)
public class Sign {
static String myToken = "";
static SOAPMessage signedRequest = null;
static SOAPEnvelope soapEnvelope = null;
static String url = "";
static String fileToSend = "";
static String receiptDir = "";
static String jksKey = "";
static String keyPwd = "";
static String privKeyAlias = "";
static TrustManagerFactory tmf = null;
public static void main(String[] args) throws Exception {
try {
url = args[0];
System.out.println(url);
fileToSend = args[1];
System.out.println(fileToSend);
receiptDir = args[2];
System.out.println(receiptDir);
jksKey = args[3];
System.out.println(jksKey);
keyPwd = args[4];
System.out.println(keyPwd);
privKeyAlias = args[5];
System.out.println(privKeyAlias);
} catch (Exception e) {
System.out.println("Paramètres incorrects !");
e.printStackTrace();
}
// Timestamp to use
SimpleDateFormat formater = null;
Date aujourdhui = new Date();
formater = new SimpleDateFormat("yyyyMMddHHmmss");
myToken = formater.format(aujourdhui);
// myToken = "20150112202835";
////////////////////////////
// Constructing the message
////////////////////////////
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
soapEnvelope = soapPart.getEnvelope();
soapEnvelope.removeNamespaceDeclaration(soapEnvelope.getPrefix());
soapEnvelope.setPrefix("soapenv");
soapEnvelope.addNamespaceDeclaration("tem", "http://tempuri.org/");
soapEnvelope.addNamespaceDeclaration("elc",
"http://schemas.datacontract.org/2004/07/ZIRE.Match.Presentation.WebService");
SOAPHeader soapHeader = soapEnvelope.getHeader();
soapHeader.setPrefix("soapenv");
Name nameSecurity = soapEnvelope.createName("Security", "wsse",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement soapSecurity = soapHeader.addChildElement(nameSecurity);
soapSecurity.addNamespaceDeclaration("wsu",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
Name nameBinSec = soapEnvelope.createName("BinarySecurityToken", "wsse",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement soapBinSec = soapSecurity.addChildElement(nameBinSec);
soapBinSec.setAttribute("EncodingType",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
soapBinSec.setAttribute("ValueType",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3");
soapBinSec.setAttribute("wsu:Id", "X509-" + myToken);
SOAPBody soapBody = soapEnvelope.getBody();
soapBody.setPrefix("soapenv");
soapBody.addAttribute(
soapEnvelope.createName("id", "wsu",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"),
"id-" + myToken);
soapBody.setIdAttribute("wsu:id", true);
////////////////////////////
// Adding the real content
////////////////////////////
// The real payload new String(readAllBytes(get("test.txt")))
String xmlValue = "<![CDATA[" + readFile(fileToSend, StandardCharsets.UTF_8) + "]]>";
// String xmlValue = "<![CDATA[" + new String(readAllBytes(get(fileToSend))) + "]]>";
// System.out.println(xmlValue);
QName sendMessage = new QName("tem:SendMessage");
QName request = new QName("tem:request");
QName xmldata = new QName("elc:XmlData");
SOAPElement sendMessageNode = soapBody.addChildElement(sendMessage);
SOAPElement requestNode = soapBody.addChildElement(request);
SOAPElement xmldataNode = soapBody.addChildElement(xmldata);
xmldataNode.addTextNode(xmlValue);
requestNode.addChildElement(xmldataNode);
sendMessageNode.addChildElement(requestNode);
Source source = soapPart.getContent();
////////////////////////////////////////////////////////
// Sending the request to the signing function
////////////////////////////////////////////////////////
Node root = ((DOMSource) source).getNode();
signedRequest = addSignature(root.getFirstChild().getOwnerDocument());
////////////////////////////////////////////////////////
// SSL mode configuration
////////////////////////////////////////////////////////
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
// Using null here initialises the TMF with the default trust store.
tmf.init((KeyStore) null);
// Get hold of the default trust manager
X509TrustManager defaultTm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
defaultTm = (X509TrustManager) tm;
break;
}
}
FileInputStream myKeys = new FileInputStream("D:\\ZIRE\\MesCertificats\\myTrustStore");
// Do the same with your trust store this time
// Adapt how you load the keystore to your needs
KeyStore myTrustStore = KeyStore.getInstance(KeyStore.getDefaultType());
myTrustStore.load(myKeys, "zire2016".toCharArray());
myKeys.close();
tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(myTrustStore);
// Get hold of the default trust manager
X509TrustManager myTm = null;
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
myTm = (X509TrustManager) tm;
break;
}
}
// Wrap it in your own class.
final X509TrustManager finalDefaultTm = defaultTm;
final X509TrustManager finalMyTm = myTm;
X509TrustManager customTm = new X509TrustManager() {
#Override
public X509Certificate[] getAcceptedIssuers() {
// If you're planning to use client-cert auth,
// merge results from "defaultTm" and "myTm".
return finalDefaultTm.getAcceptedIssuers();
}
#Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
try {
finalMyTm.checkServerTrusted(chain, authType);
} catch (CertificateException e) {
// This will throw another CertificateException if this fails too.
finalDefaultTm.checkServerTrusted(chain, authType);
}
}
#Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
// If you're planning to use client-cert auth,
// do the same as checking the server.
finalDefaultTm.checkClientTrusted(chain, authType);
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { customTm }, null);
// You don't have to set this as the default context,
// it depends on the library you're using.
SSLContext.setDefault(sslContext);
////////////////////////////////////////////////////////
// Sending the request to the receiver
////////////////////////////////////////////////////////
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
// System.setProperty("javax.net.ssl.trustStore", "D:\\ZIRE\\MesCertificats\\myTrustStore" );
// System.setProperty("javax.net.ssl.trustStorePassword", "zire2016");
// System.setProperty("java.net.useSystemProxies", "true");
// SOAPMessage soapResponse = soapConnection.call(signedRequest, url);
// doTrustToCertificates();
SOAPMessage soapResponse = sendMessage(signedRequest, url);
////////////////////////////////////////////////////////
// Processing the response
////////////////////////////////////////////////////////
// Cleaning of the response
ByteArrayOutputStream out = new ByteArrayOutputStream();
soapResponse.writeTo(out);
String strMsg = new String(out.toByteArray());
int d = strMsg.indexOf("<s:Envelope");
int f = strMsg.indexOf("</s:Envelope>") + 13;
String strMsg2 = strMsg.substring(d, f);
// System.out.println(strMsg2);
// Writting of the response on the server
// PrintWriter printWriter = new PrintWriter("D:\\ZIRE\\Result.xml");
// fileToSend
// String receiptFileName = (new File(fileToSend)).getParent() + "Receipt_" + (new File(fileToSend)).getName();
// System.out.println(receiptFileName);
// Writing the response
String receiptFileName = receiptDir + "Receipt_" + (new File(fileToSend)).getName();
System.out.println(receiptFileName);
PrintWriter printWriter = new PrintWriter( receiptFileName );
printWriter.println(strMsg2);
printWriter.close();
soapConnection.close();
}
public static SOAPMessage addSignature(Document contenu)
throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, CertificateException,
IOException, InvalidAlgorithmParameterException, InstantiationException, IllegalAccessException,
ClassNotFoundException, KeyException, SAXException, ParserConfigurationException, MarshalException,
XMLSignatureException, TransformerException, InvalidKeySpecException, XMLSecurityException, SOAPException {
// Chargement des clés
// FileInputStream is = new FileInputStream("D:\\ZIRE\\Step 1\\mock\\NewJKS.jks");
FileInputStream is = new FileInputStream(jksKey);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(is, null);
// tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); // PKIX
// tmf.init(keystore);
// Enumeration<String> myEnum = keystore.aliases();
// for (Enumeration<String> e = keystore.aliases(); e.hasMoreElements();) {
// String newAlias = e.nextElement();
// System.out.println(newAlias);
// if (newAlias != "wsgbit" ) {
// System.out.println(keystore.getCertificate(newAlias));
// }
// }
// Recup clé privée
// String alias = "wsgbit";
String alias = privKeyAlias;
// Key key = keystore.getKey(alias, "password".toCharArray());
Key key = keystore.getKey(alias, keyPwd.toCharArray());
KeyPair kp = null;
Certificate cert = null;
if (key instanceof PrivateKey) {
// Get certificate of public key
cert = keystore.getCertificate(alias);
// Get public key
PublicKey publicKey = cert.getPublicKey();
// Return a key pair
kp = new KeyPair(publicKey, (PrivateKey) key);
}
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = contenu;
// dumpDocument(doc);
// MAJ du champ wsse:BinarySecurityToken
Element elt = doc.getDocumentElement();
Node myBinSecElt = (Node) (elt.getElementsByTagName("wsse:BinarySecurityToken")).item(0);
myBinSecElt.setTextContent(Utf8.decode(Base64.encode(cert.getEncoded())));
// Debut
org.apache.xml.security.Init.init();
Node mySecElt = (Node) (elt.getElementsByTagName("wsse:Security")).item(0);
org.apache.xml.security.signature.XMLSignature xmlSignature = new org.apache.xml.security.signature.XMLSignature(
doc, "", org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1,
"http://www.w3.org/2001/10/xml-exc-c14n#");
Element eltSign = xmlSignature.getElement();
eltSign.setAttribute("Id", "SIG-" + myToken);
mySecElt.appendChild(eltSign);
Transforms transforms = new Transforms(doc);
transforms.addTransform("http://www.w3.org/2001/10/xml-exc-c14n#");
xmlSignature.addDocument("#id-" + myToken, transforms, Constants.ALGO_ID_DIGEST_SHA1);
SOAPElement myCanonElt = (SOAPElement) (elt.getElementsByTagName("ds:CanonicalizationMethod")).item(0);
InclusiveNamespaces inclusiveNamespaces = new InclusiveNamespaces(doc, "elc soapenv tem");
myCanonElt.appendChild(inclusiveNamespaces.getElement());
SOAPElement mySoapTransform = (SOAPElement) (elt.getElementsByTagName("ds:Transform")).item(0);
InclusiveNamespaces inclusiveNamespaces2 = new InclusiveNamespaces(doc, "elc tem");
mySoapTransform.appendChild(inclusiveNamespaces2.getElement());
// Ajustements
// SOAPElement myCanonElt = (SOAPElement)
// (elt.getElementsByTagName("ds:CanonicalizationMethod")).item(0);
// myCanonElt.setAttribute("Algorithm",
// "http://www.w3.org/2001/10/xml-exc-c14n#");
// Name nameInclusiveNamespaces =
// soapEnvelope.createName("InclusiveNamespaces", "ec",
// "http://www.w3.org/2001/10/xml-exc-c14n#");
// SOAPElement soapInclusiveNamespaces =
// myCanonElt.addChildElement(nameInclusiveNamespaces);
// soapInclusiveNamespaces.setAttribute("PrefixList", "elc soapenv
// tem");
//
// SOAPElement mySoapTransform = (SOAPElement)
// (elt.getElementsByTagName("ds:Transform")).item(0);
// Name nameInclusiveNamespaces2 =
// soapEnvelope.createName("InclusiveNamespaces", "ec",
// "http://www.w3.org/2001/10/xml-exc-c14n#");
// SOAPElement soapInclusiveNamespaces2 =
// mySoapTransform.addChildElement(nameInclusiveNamespaces2);
// soapInclusiveNamespaces2.setAttribute("PrefixList", "elc tem");
//
Name nameKeyInfo = soapEnvelope.createName("KeyInfo", "ds", "http://www.w3.org/2000/09/xmldsig#");
SOAPElement mySoapSign = (SOAPElement) (elt.getElementsByTagName("ds:Signature")).item(0);
SOAPElement soapKeyInfo = mySoapSign.addChildElement(nameKeyInfo);
soapKeyInfo.setAttribute("Id", "KI-" + myToken);
Name nameSecToken = soapEnvelope.createName("SecurityTokenReference", "wsse",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement soapSecToken = soapKeyInfo.addChildElement(nameSecToken);
soapSecToken.setAttribute("wsu:Id", "STR-" + myToken);
Name nameRef = soapEnvelope.createName("Reference", "wsse",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement soapNameRef = soapSecToken.addChildElement(nameRef);
soapNameRef.setAttribute("URI", "#X509-" + myToken);
soapNameRef.setAttribute("ValueType",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3");
xmlSignature.sign(key);
// xmlSignature.sign(key);
// dumpDocument(doc);
// String xml = new XMLOutputter().outputString(doc);
// Ecriture du String represantant la requete signée
StringWriter sw = new StringWriter();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
// transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
// transformer.setOutputProperty(OutputKeys.METHOD, "xml");
// transformer.setOutputProperty(OutputKeys.INDENT, "no");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.transform(new DOMSource(doc), new StreamResult(sw));
// String xml = sw.toString(); System.out.println(">>>" + xml + "<<<");
InputStream inputStream = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));// new
// InputStream(xml);
MessageFactory messageFactory = MessageFactory.newInstance();
return messageFactory.createMessage(null, inputStream);
// Ecriture dans un fichier
// Transformer transformer =
// TransformerFactory.newInstance().newTransformer();
// Result output = new StreamResult(new
// FileOutputStream("D:\\ZIRE\\mySignedFile2.xml"));
// Source input = new DOMSource(doc);
// transformer.transform(input, output);
}
public static String convertToString(Document document) throws TransformerException {
DOMSource domSource = new DOMSource(document);
StringWriter sw = new StringWriter();
Result result = new StreamResult(sw);
// create an instance of TransformerFactory
TransformerFactory transFact = TransformerFactory.newInstance();
Transformer trans = transFact.newTransformer();
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
trans.transform(domSource, result);
return sw.toString();
}
private static void dumpDocument(Node root) throws TransformerException {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
// transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(new DOMSource(root), new StreamResult(System.out));
}
private static Element getFirstChildElement(Node node) {
Node child = node.getFirstChild();
while ((child != null) && (child.getNodeType() != Node.ELEMENT_NODE)) {
child = child.getNextSibling();
}
return (Element) child;
}
public static Element getNextSiblingElement(Node node) {
Node sibling = node.getNextSibling();
while ((sibling != null) && (sibling.getNodeType() != Node.ELEMENT_NODE)) {
sibling = sibling.getNextSibling();
}
return (Element) sibling;
}
static String readFile(String path, Charset encoding) throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
static public SOAPMessage sendMessage(SOAPMessage message, String endPoint) throws SOAPException, IOException {
SOAPMessage result = null;
if (endPoint != null && message != null) {
URL url;
SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance();
SOAPConnection connection = null;
try {
connection = scf.createConnection(); //point-to-point connection
url = new URL(endPoint);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.connect();
result = connection.call(message, url);
} finally {
if (connection != null) {
try {
connection.close();
} catch (SOAPException soape) {
System.out.print("Can't close SOAPConnection:" + soape);
}
}
}
}
return result;
}
static public void doTrustToCertificates() throws Exception {
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
if (!urlHostName.equalsIgnoreCase(session.getPeerHost())) {
System.out.println("Warning: URL host '" + urlHostName + "' is different to SSLSession host '" + session.getPeerHost() + "'.");
}
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
}
}
Wireshark has shown me I am not sending my certificate though I am using JVM params like -Djavax.net.ssl.keyStore=...
But I am wondering how can the JVM know where is my certificate as I can have many certificates in a jks file ???
if you want to call a https-site you do not have to send a cert by default. the server has to send and your client will eval it (by uri, expiry-date, cert-chain, ...). if the cert is valid your http-client should accept it by default.
in other cases you can import the cert of the server to your local keystore (jks) and the client will accept it, cause you never would import "untrusted" certs to your local keystore.
or you implement a code like "who cares the cert? just do it!" (link: telling java to accept self-signed ssl certificate).
but this is not supposed to be used in public/prod environment (like internet)
I have the following Issue:
I'm making an application that sends an already digitally signed XML certificate to an official govt. Webservice.
When I generate the SOAP message, I copy the whole file to a string (I've used several techniques to do this: Guava's File.toString, Files.readAllBytes(Paths.get(path), and tried it with all relevant encodings (UTF-8 and ISO-8859-1, since the document is in spanish). I use logger to store the content of the soap message just before sending it.
The issue is that the webservice gives me an "Invalid signature" answer, but when I copy the soap message from the log, and send it via SoapUI, the webservice accepts the signed certificate.
Here's the code that does the magic:
public class SOAPClientSAAJ {
public static void SendMessage(String file, String rscpath) throws Exception {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
GetCurrentTimeStamp cts = new GetCurrentTimeStamp();
Logger logger = Logger.getLogger("MyLog");
FileHandler fh;
String logfile = rscpath+cts.GetCurrentTimeStamp()+".log";
try {
// This block configure the logger with handler and formatter
fh = new FileHandler(logfile);
logger.addHandler(fh);
SimpleFormatter formatter = new SimpleFormatter();
fh.setFormatter(formatter);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// Send SOAP Message to SOAP Server
String url = "http://172.25.1.220:8080/SGPRTWebServices/RecepcionCrt";
SOAPMessage soapResponse = null;
SOAPMessage soapmsg = null;
logger.info(file.substring(file.lastIndexOf(File.separator)));
soapmsg = createSOAPRequest(file);
ByteArrayOutputStream out = new ByteArrayOutputStream();
soapmsg.writeTo(out);
String msg = new String(out.toByteArray());
logger.info(msg);
out = null;
msg = null;
try{
soapResponse = soapConnection.call(soapmsg, url);
SOAPPart sp = soapResponse.getSOAPPart();
SOAPEnvelope se = sp.getEnvelope();
SOAPBody sb = se.getBody();
ByteArrayOutputStream out2 = new ByteArrayOutputStream();
soapResponse.writeTo(out2);
msg = new String(out2.toByteArray());
logger.info(msg);
}catch (Exception ex) {
logger.info(ex.toString());
}
soapConnection.close();
}
private static SOAPMessage createSOAPRequest(String confFilePath) throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
String serverURI = "http://recepcionCrt.ws.sgprt.mtt.cl/";
Path pat =Paths.get(confFilePath);
Charset charset = StandardCharsets.ISO_8859_1;
String texto = "<![CDATA[";
File fl = pat.toFile();
String content = Files.toString(fl, charset);
texto = texto + content +"]]>";
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.setEncodingStyle("UTF-8");
SOAPBody soapBody = envelope.getBody();
soapBody.addNamespaceDeclaration("ns2", serverURI);
SOAPElement soapBodyElem = soapBody.addChildElement ("recepcionCRT","ns2");
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement ("arg0");
soapBodyElem1.addTextNode(texto);
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", serverURI + "recepcionCRT");
soapMessage.saveChanges();
return soapMessage;
}
}
Here:can you check some files like the wsdl, a valid certificate and a valid soap message.
As it turned out, the problem was in the communication process. I had to use the importws tool from the jdk to load the interfaces and clases to comunicate with the provider. Once I did that, the message was recieved correctly and the signature verified.
I have a simple SOAP webservice server like this:
public class receiver extends JAXMServlet implements ReqRespListener {
public SOAPMessage onMessage(SOAPMessage soapm) {
return soapm;
}
}
In the client I send a message to this server:
public class sender {
/** This is a sample web service operation */
SOAPConnectionFactory scfac = null;
SOAPConnection con =null;
MessageFactory fac = null;
SOAPMessage message = null;
SOAPMessage response = null;
#WebMethod(operationName = "sender")
public String sender(#WebParam(name = "a") String a)
{
try{
//Creat Connection
scfac = SOAPConnectionFactory.newInstance();
con = scfac.createConnection();
fac = MessageFactory.newInstance();
message = fac.createMessage();
SOAPPart soapPart = message.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
SOAPHeader header = envelope.getHeader();
header.detachNode();
SOAPBody body = envelope.getBody();
body.addTextNode(a);
URL endpoint = new URL("http://localhost:8080/Target/receiver");
//log("Bat dau gui");
response = con.call(message, endpoint);
//log("Da nhan ve");
SOAPPart sp = response.getSOAPPart();
SOAPEnvelope ev = sp.getEnvelope();
SOAPBody bd = ev.getBody();
String result = bd.getValue();
return result;
}
catch (Exception e)
{
String fail = "Fail to send";
return fail;
}
}
}
I called the sender function in a jsp file and passed a String to it.
I had built it with Netbeans and Tomcat server but it just responds with a null message.
How can I fix the problem?
I had fixed the problem by 2 steps:
The SOAP server: In the web.xml file fix the servlet class from com.sun.xml.ws.transport.http.servlet.WSServlet to your own Java class (in my case it is receive.receiver)
Add saaj-impl-1.3.1 library to NetBeans (the library with method com.sun.xml.messaging)