Sign SOAP message with WS-Security - java

I need to consume a SOAP API which requests all the messages to be signed policy "SigOnly".
I've generated the client code from the WSDL using wsimport and I was expecting it to generate the code for signing as well but it's not.
MyWebservice service = new MyWebservice();
MyWebservicePortType port = service.getMyWebserviceSOAPportHttp();
// Build request
ObjectFactory objectFactory = new ObjectFactory();
MyRequest request = objectFactory.createMyRequest();
// Call endpoint
port.myRemoteMethod(request);
Is there an extra switch for the wsimport tool to generate code for signing or am I missing some steps in the client's code?

WS-Security is an extension to soap, so I don't think wsimport could handle it in code generation.
Anyway you can write your handler to add ws-security headers in your soap requests.
You can add a handler to your port in this way :
BindingProvider bp = (BindingProvider) port;
List<Handler> handlerChain = new ArrayList<Handler>();
handlerChain.add( new MyHandler() );
Binding binding = bp.getBinding();
binding.setHandlerChain(handlerChain);
MyHandler class must implement SOAPHandler.
This is an example of an implementation of handleMessage method of MyHandler, adding a header
#Override
public boolean handleMessage(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();
SOAPHeader header = envelope.addHeader();
SOAPElement security = header.addChildElement("Security", "wsse",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement usernameToken = security.addChildElement("UsernameToken", "wsse");
SOAPElement username = usernameToken.addChildElement("Username", "wsse");
username.addTextNode("MyUser");
}
}

Related

Spring-WS SOAP header prefix issues

I'm working on a Spring-WS project and I'm trying to consume a certain SOAP service but I'm getting some issues with the request's Header tag.
PS: I ran the same request on SOAP UI and it works perfectly.
This is the code I ran:
JAXBElement<ChangeOtherIDsRequestType> request = createRequestBody();
WebServiceTemplate template = new WebServiceTemplate(marshaller);
template.setDefaultUri(URI);
#SuppressWarnings({ "unchecked" })
JAXBElement<ChangeOtherIDsResponseType> response = (JAXBElement<ChangeOtherIDsResponseType>) template
.marshalSendAndReceive(request, new WebServiceMessageCallback() {
#Override
public void doWithMessage(WebServiceMessage message) {
Instant instant = Instant.now();
SaajSoapMessage saajSoapMessage = (SaajSoapMessage) message;
SOAPMessage soapMessage = saajSoapMessage.getSaajMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
try {
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
SOAPHeader soapHeader = soapEnvelope.getHeader();
Name headerElementName = soapEnvelope.createName("Security", "wsse",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
// Add "Security" soapHeaderElement to soapHeader
SOAPHeaderElement soapHeaderElement = soapHeader.addHeaderElement(headerElementName);
soapHeaderElement.setMustUnderstand(true);
soapHeaderElement.addNamespaceDeclaration("wsu",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
// Add usernameToken to "Security" soapHeaderElement
SOAPElement usernameTokenSOAPElement = soapHeaderElement.addChildElement("UsernameToken",
"wsse");
// Add username to usernameToken
QName userQname = soapHeaderElement.createQName("Username", "wsse");
SOAPElement userNameSOAPElement = usernameTokenSOAPElement.addChildElement(userQname);
userNameSOAPElement.addTextNode("username");
// Add password to usernameToken
QName passwordQname = usernameTokenSOAPElement.createQName("Password", "wsse");
SOAPElement passwordSOAPElement = usernameTokenSOAPElement.addChildElement("Password");
passwordSOAPElement.setAttribute("Type",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
passwordSOAPElement.addTextNode("password");
// Add Nonce to usernameToken.
QName nonceQname = soapHeaderElement.createQName("Nonce", "wsse");
SOAPElement nonceSOAPElement = usernameTokenSOAPElement.addChildElement("Nonce");
nonceSOAPElement.setAttribute("EncodingType",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
// Add Created to usernameToken.
QName createdQname = soapHeaderElement.createQName("Created", "wsu");
SOAPElement createdElement = usernameTokenSOAPElement.addChildElement(createdQname);
createdElement.addTextNode(instant.toString());
} catch (SOAPException | UnsupportedEncodingException e) {
e.printStackTrace();
}
}
});
template.marshalSendAndReceive(URI, request);
This code is supposed to add the Header tag in the request and it serves to authenticate the user through "username" and "password".
The result I'm expecting is the same that is generated by SOAP UI for the same request. The result is this:
<SOAP-ENV:Header>
<wsse:Security SOAP-ENV:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-C17C5A667A3F11A8DA153735499778322">
<wsse:Username>username</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">Tl6jznnHitsSE9F16FWTsw==</wsse:Nonce>
<wsu:Created>2018-09-19T11:03:17.783Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
But the result I'm getting looks like this:
<SOAP-ENV:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" SOAP-ENV:mustUnderstand="1">
<wsse:UsernameToken>
<wsse:Username>username</wsse:Username>
<Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</Password>
<Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"> </Nonce>
<wsu:Created>2018-09-19T11:02:21.918Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
Let's see that there are some things that are missing in my result such as:
"wsse" prefix on the tags "Password" and "Nonce".
"UsernameToken" attribute on the "Username" tag.
The value of "Nonce" tag.
I faced some issues when trying to fix these things but I still have some problems:
When I try to add "wsse" prefix to "Username" and "Nonce" tags: the whole "Header" tag dissapears. (I used the same technique as in the "Username" tag)
How does SOAP UI generate the "Nonce" value ?
How does SOAP UI generate the "UsernameToken" value ?
Last resort, is there another way to mock the SOAP UI request ?
Thanks in advance.
You are trying to shoehorn security into your request whereas there is an interceptor and default way of doing that. Configure the Wss4jSecurityInterceptor for your WebServiceTemplate.
Something like the following should do the trick.
#Bean
public Wss4jSecurityInterceptor securityInterceptor() {
Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
interceptor.setSecurementUsername("username");
interceptor.setSecurementPassword("password");
interceptor.setSecurementUsernameTokenNonce(true);
interceptor.setSecurementActions("UsernameToken Timestamp");
return interceptor;
}
Then inject this into your WebServiceTemplate. That should add the needed headers without you having to do anything else. Ideally you would configure the WebServiceTemplate once and reuse it.
#Bean
public WebServiceTemplate webServiceTemplate(Marshaller marshaller) {
WebServiceTemplate wsTemplate = new WebServiceTemplate(marshaller);
wsTemplate.setInterceptors(new ClientInterceptor[]{ securityInterceptor() });
return wsTemplate;
}
Then use the pre configured WebServiceTemplate in your code.

How to add xmlbean document element to soap header spring-ws

I am trying to hit a webservice using spring-ws, but the webservice producer requires a custom element in the soap header. I am very new to webservices, and am having trouble trying to inject the values into the soap header. I am using XMLBeans to transform from xsd to java and also to do the marshaling and unmarshaling. I have constructed the xmlbean document and set all values for the custom header element, I just need to get the document or maybe even just the element attached to that document to be injected into the soap header. Listed below is the wsdl (just header) in soapui (what I used to learn and do initial testing)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0" xmlns:v11="http://www.ups.com/XMLSchema/XOLTWS/Rate/v1.1" xmlns:v12="http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0">
<soapenv:Header>
<v1:UPSSecurity>
<v1:UsernameToken>
<v1:Username>name</v1:Username>
<v1:Password>password</v1:Password>
</v1:UsernameToken>
<v1:ServiceAccessToken>
<v1:AccessLicenseNumber>accesskey</v1:AccessLicenseNumber>
</v1:ServiceAccessToken>
</v1:UPSSecurity>
</soapenv:Header>
I found a solution that works, and isn't much code. I had to ditch using xmlbeans, and just create the elements, but at least the functionality is there and the webservice calls works.
#Override
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException
{
try
{
SOAPMessage soapMessage = ((SaajSoapMessage)message).getSaajMessage();
SOAPHeader header = soapMessage.getSOAPHeader();
SOAPHeaderElement soapHeaderElement = header.addHeaderElement(new QName("http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0", "UPSSecurity", "v1"));
SOAPEnvelope envelope = soapMessage.getSOAPPart().getEnvelope();
envelope.addNamespaceDeclaration("v1", "http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0");
SOAPElement usernameToken = soapHeaderElement.addChildElement("UsernameToken", "v1");
SOAPElement username = usernameToken.addChildElement("Username", "v1");
SOAPElement password = usernameToken.addChildElement("Password", "v1");
SOAPElement serviceAccessToken = soapHeaderElement.addChildElement("ServiceAccessToken", "v1");
SOAPElement accessLicenseNumber = serviceAccessToken.addChildElement("AccessLicenseNumber", "v1");
username.setTextContent("username");
password.setTextContent("password");
accessLicenseNumber.setTextContent("key");
}
catch (SOAPException e)
{
e.printStackTrace();
}
}
You can marshal to a SoapHeader's Result, like so:
SoapMessage msg = ...
SoapHeader header = msg.getSoapHeader();
XmlBeansMarshaller marshaller = ...
MyXmlBeansDocument doc = ...
marshaller.marshal(doc, header.getResult());
You can convert an XmlObject (XmlBeans model) to a SOAPElement using the following factory method:
YourModel xmlObject = YourModelDocument.Factory.newInstance().addNewYourModel();
SOAPElement soapElement = SOAPFactory.newInstance()
.createElement((Element) xmlObject.getDomNode());
The XmlObject must be part of a document otherwise getDomNode() will return an XmlFragment rather than an Element.
Once converted to a SOAP element, the XML can be added to most parts of a SOAPMessage using addChildElement(). For example:
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
soapMessage.getSOAPBody().addChildElement(soapElement);

Calling a soap webservice from java with nonce in security headers

I am trying to call a webservice from java. This is basically not that difficult, except that the webservice expects some security in the form of a username and password and a nonce.
When I try to call the webservice from SoapUi, I see that the raw message looks like this:
<soapenv:Envelope xmlns:sch="http://somedomain.com/pe/ws/schema"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-E70691ACBDEFEC750814238295617871">
<wsse:Username>usr</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"
>pw</wsse:Password>
<wsse:Nonce
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
>4smQZF5KMSktEXrQc0v5yw==</wsse:Nonce>
<wsu:Created>2015-02-13T12:12:41.784Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<sch:EventSubmitRequest>
<sch:Event>
<sch:EventId>392</sch:EventId>
<sch:Recoverable>false</sch:Recoverable>
</sch:Event>
</sch:EventSubmitRequest>
</soapenv:Body>
</soapenv:Envelope>
The obvious elements in the message are the Username, Password and Created, but what puzzles me is the nonce. In the example this field has the value 4smQZF5KMSktEXrQc0v5yw==, but this value difference upon each request (which makes sense, since according to wikipedia, a nonce is an arbitrary number used only once). When searching around, I can't find any usable examples of how to generate the nonce in java (Although I did find some php examples here on stack overflow, but I can't easily verify weather they work) . While I don't mind construction this nonce myself, I'm wondering if this is really necessary, I kind of would expect this to be standard functionality in java.
Below is the code I'm using:
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.xml.namespace.QName;
import javax.xml.soap.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
public class soaptest {
public static void main(String args[]) {
try {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
String url = "http://142.10.10.52:8080/pe/ws/pe/";
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);
// Process the SOAP Response
printSOAPResponse(soapResponse);
soapConnection.close();
} catch (Exception e) {
System.err.println("Error occurred while sending SOAP Request to Server");
e.printStackTrace();
}
}
private static SOAPMessage createSOAPRequest() throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
SOAPHeader header = soapMessage.getSOAPHeader();
SOAPElement security = header.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement usernameToken = security.addChildElement("UsernameToken", "wsse");
usernameToken.addAttribute(new QName("xmlns:wsu"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
SOAPElement username = usernameToken.addChildElement("Username", "wsse");
username.addTextNode("usr");
SOAPElement password = usernameToken.addChildElement("Password", "wsse");
password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
password.addTextNode("pw");
SOAPElement nonce = usernameToken.addChildElement("Nonce", "wsse");
nonce.setAttribute("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
nonce.addTextNode("???");
SOAPElement created = usernameToken.addChildElement("Created", "wsse");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Calendar c1 = Calendar.getInstance();
created.addTextNode(sdf.format(c1.getTime()));
String serverURI = "http://somedomain.com/pe/ws/schema";
envelope.addNamespaceDeclaration("sch", serverURI);
// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("EventSubmitRequest", "sch");
SOAPElement soapBodyElem1 = soapBody.addChildElement("Event", "sch");
soapBodyElem.addChildElement(soapBodyElem1);
SOAPElement soapBodyElem2 = soapBodyElem1.addChildElement("EventId", "sch");
soapBodyElem2.addTextNode("392");
SOAPElement soapBodyElem3 = soapBodyElem1.addChildElement("Recoverable", "sch");
soapBodyElem3.addTextNode("false");
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", serverURI + "EventSubmitRequest");
soapMessage.saveChanges();
/* Print the request message */
System.out.print("Request SOAP Message = ");
soapMessage.writeTo(System.out);
System.out.println();
return soapMessage;
}
/**
* Method used to print the SOAP Response
*/
private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
Source sourceContent = soapResponse.getSOAPPart().getContent();
System.out.print("\nResponse SOAP Message = ");
StreamResult result = new StreamResult(System.out);
transformer.transform(sourceContent, result);
}
}
The Oasis reference for the UsernameToken helped me fill in some of the blanks. Pages 7,8,9 are most appropriate in this case. In particular these sections
/wsse:UsernameToken/wsse:Nonce
This optional element specifies a cryptographically random nonce. Each message
including a element MUST use a new nonce value in order for web
service producers to detect replay attacks.
and
/wsse:UsernameToken/wsse:Nonce/#EncodingType
This optional attribute URI specifies the encoding type of the nonce (see the definition of
<wsse:BinarySecurityToken> for valid values). If this attribute isn't specified then
the default of Base64 encoding is used.
In regards to generating the 'cryptographically random' nonce, can suggest you use this answer and then create an encoded string from it. Base64 encoding in your case, as that is the encodingType you are using in your XML request above.
For Spring WS users: check securityPolicy.xml contains line
<xwss:RequireUsernameToken passwordDigestRequired="false" nonceRequired="true" />
It fixes exception Receiver Requirement for nonce has not been met for SoapUi.
In case there is no "nonce" in request, set
nonceRequired="false"

Soap Web Service client from java class using saaj

I am working in application in wish i need to invoke soap web services. To do so i am using SAAJ. For testing I made the method below to call a service. This service return a String that receives as input.my problem is that the service is called but it doesn't receive the input parameters. Can anyone give me an idea about how to resolve this please?
2. I have also another question, how can i do to invoke a service who has objects as input?
3. is SAAJ the best solution to create distant client to invoque soap services?
Thank you
public void invokeExtractMetadata(Service service,String path) throws Exception {
System.out.println("invoke");
QName serviceName = new QName(service.namespace, service.serviceName);
QName portName = new QName(service.namespace, service.portType);
String endpointAddress =service.endPointAddress;
javax.xml.ws.Service myService = javax.xml.ws.Service.create(serviceName);
myService.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);
Dispatch<SOAPMessage> dispatch = myService.createDispatch(portName, SOAPMessage.class, javax.xml.ws.Service.Mode.MESSAGE);
BindingProvider bp = (BindingProvider) dispatch; //Use Dispatch as BindingProvider
MessageFactory factory = ((SOAPBinding) bp.getBinding()).getMessageFactory();
SOAPMessage request = factory.createMessage();
// Request Header
SOAPHeader header = request.getSOAPHeader();
// Request Body
SOAPBody body = request.getSOAPBody();
// Compose the soap:Body payload
QName payloadName = new QName(service.namespace,service.inMsgTag );
SOAPBodyElement payload = body.addBodyElement(payloadName);
QName name = new QName("pathT");
SOAPElement message = payload.addChildElement(name);
message.addTextNode(path);
SOAPMessage reply = null;
//Invoke Endpoint Operation and read response
reply = dispatch.invoke(request);
//process the reply
body = reply.getSOAPBody();
QName responseName = new QName(service.namespace, service.outMsgTag);
SOAPBodyElement bodyElement = (SOAPBodyElement)body.getChildElements(responseName).next();
QName elementName = new QName("", "return");
Iterator t =bodyElement.getChildElements(elementName);
System.out.println("tt");
while(t.hasNext()){
SOAPBodyElement bodyElementTest = (SOAPBodyElement)t.next();
String valeur = bodyElementTest.getValue();
System.out.println("valeur"+valeur);
}
}

SSLHandshakeException: No subject alternative names present

I am invoking HTTPS SOAP web service through java code. I have already imported self-signed certificate in jre cacerts keystore. Now I am getting :
com.sun.xml.internal.ws.com.client.ClientTransportException: HTTP transport error: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present
The hostname of the service URL is not matching that of the CN provided in cert. I read about a workaround of defining a custom Hostname verifier here. But i cant able to make where I should implement the workaround in my code.
public SOAPMessage invokeWS(WSBean bean) throws Exception {
SOAPMessage response=null;
try{
/** Create a service and add at least one port to it. **/
String targetNameSpace = bean.getTargetNameSpace();
String endpointUrl = bean.getEndpointUrl();
QName serviceName = new QName(targetNameSpace, bean.getServiceName());
QName portName = new QName(targetNameSpace, bean.getPortName());
String SOAPAction = bean.getSOAPAction();
HashMap<String, String> map = bean.getParameters();
Service service = Service.create(serviceName);
service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointUrl);
/** Create a Dispatch instance from a service. **/
Dispatch dispatch = service.createDispatch(portName, SOAPMessage.class,
Service.Mode.MESSAGE);
// The soapActionUri is set here. otherwise we get a error on .net based
// services.
dispatch.getRequestContext().put(Dispatch.SOAPACTION_USE_PROPERTY,
new Boolean(true));
dispatch.getRequestContext().put(Dispatch.SOAPACTION_URI_PROPERTY,
SOAPAction);
/** Create SOAPMessage request. **/
// compose a request message
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage message = messageFactory.createMessage();
// Create objects for the message parts
SOAPPart soapPart = message.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
SOAPBody body = envelope.getBody();
SOAPElement bodyElement = body.addChildElement(bean.getInputMethod(),
bean.getPrefix(), bean.getTargetNameSpace());
...more code to form soap body goes here
// Print request
message.writeTo(System.out);
// Save the message
message.saveChanges();
response = (SOAPMessage)dispatch.invoke(message);
}
catch (Exception e) {
log.error("Error in invokeSiebelWS :"+e);
}
return response;
}
Please ignore WSBean parameter as the namespaces and other wsdl attributes are coming from this bean. And if this exception can solved with some different workarounds, pls do suggest.
Thanks,Bruno for giving me heads up on Common Name and Subject Alternative Name. As we figured out certificate was generated with CN with DNS name of network and asked for regeneration of new certificate with Subject Alternative Name entry i.e. san=ip:10.0.0.1. which is the actual solution.
But, we managed to find out a workaround with which we can able to run on development phase. Just add a static block in the class from which we are making ssl connection.
static {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
{
public boolean verify(String hostname, SSLSession session)
{
// ip address of the service URL(like.23.28.244.244)
if (hostname.equals("23.28.244.244"))
return true;
return false;
}
});
}
If you happen to be using Java 8, there is a much slicker way of achieving the same result:
static {
HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> hostname.equals("127.0.0.1"));
}
Unlike some browsers, Java follows the HTTPS specification strictly when it comes to the server identity verification (RFC 2818, Section 3.1) and IP addresses.
When using a host name, it's possible to fall back to the Common Name in the Subject DN of the server certificate, instead of using the Subject Alternative Name.
When using an IP address, there must be a Subject Alternative Name entry (of type IP address, not DNS name) in the certificate.
You'll find more details about the specification and how to generate such a certificate in this answer.

Categories