I am consuming a web service (I cannot reveal the name due to being confidential). The web service requires me to login w/ username and password before I get the wsdl page. For example, if I enter the service url in a web server, it prompts me to enter the login information.
So, I am assuming need to first authenticate myself, then use the wsdl.
However, I wrote some test code that consumes the w3schools Celsius to Fahrenheit service, which DOES NOT require authentication and works perfectly.
<!--- soap request in xml --->
<cfsavecontent variable="soap">
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="http://www.w3schools.com/webservices/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<SOAP-ENV:Body>
<tns:CelsiusToFahrenheit xmlns:tns="http://www.w3schools.com/webservices/">
<tns:Celsius>34</tns:Celsius>
</tns:CelsiusToFahrenheit>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
</cfsavecontent>
<!---Sending a post request accessing the defined SOAPAction CelsiusToFahrenheit--->
<cfhttp url="http://www.w3schools.com/webservices/tempconvert.asmx" method="post" result="httpresponse">
<cfhttpparam type="header" name="content-type" value="text/xml">
<cfhttpparam type="header" name="SOAPAction" value="""http://www.w3schools.com/webservices/CelsiusToFahrenheit""">
<cfhttpparam type="header" name="content-length" value="#len(soap)#">
<cfhttpparam type="header" name="charset" value="utf-8">
<cfhttpparam type="xml" name="message" value="#trim(soap)#">
</cfhttp>
<!---Output the result if http status is 200 (we can do error handling also) --->
<cfif find( "200", httpresponse.statusCode )>
<cfset soapResponse = xmlParse(httpresponse.fileContent) />
<cfset responseNodes = xmlSearch(soapResponse, "//*[ local-name() = 'CelsiusToFahrenheitResult' ]") />
<cfoutput>Fahrenheit: #responseNodes[ 1 ].xmlText#</cfoutput>
</cfif>
Is there anyway I could adapt this to ask for the authenticated web service? Please note this question may be somewhat vague. However, please comment to let me know if you need more information.
EDIT: When I adapted the code for my web service, it says I have a hand-shake failure.
EDIT: added the wsdl file (changed the namespace): [dump] http://dumptext.com/vy7Fj2da
There are a few reasons why you might be getting a hand-shake failure:
If you are using ColdFusion 9 or earlier version you are sending a SSLv2 Client Hello for a hand-shake. Most likely because of new PCI regulation the other side has that turned off and that is why you are getting a failure. Your options to fix this are:
Upgrade ColdFusion to version 10/11
Upgrade the Java version of your current ColdFusion to 1.7
Use the following custom tag that doesn't use underling Java classes to make the connection: cfx_http5 (http://adiabata.com/cfx_http5.cfm)
The other side has a SSL certificate that you need to install in your ColdFusion store to make a successful connection. Something like this:
keytool -importcert -v -alias [alias name] -file [location of certificate file] -keystore D:\ColdFusion9\runtime\jre\lib\security\cacerts -storepass changeit
Related
I have this simple GET call that works perfectly from Postman, Powershell, C# and even browser JS ( after disabling CORS ), but porting it to a ColdFusion CFHTTP call is failing.
Below is the response from the Jira API:
{
"ErrorDetail": "I/O Exception: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target",
"Mimetype": "Unable to determine MIME type of file.",
"Filecontent": "Connection Failure",
"Statuscode": "Connection Failure. Status code unavailable.",
"Responseheader": {
},
"Text": true,
"Charset": "",
"Header": ""
}
CF Code:
<cfset jql="<redacted>">
<cfset jiraEndpoint ='https://jira.bullhorn.com/rest/api/2/search?jql=#jql#'>
<cfhttp url = "#jiraEndpoint#" result="res" method="get" username="<redacted>" password="<redacted>">
<cfhttpparam type="header" name="Accept" value="application/json" />
</cfhttp>
<cfheader name="Content-Type" value="application/json">
<cfoutput>
#serializeJSON(res)#
</cfoutput>
Things I have tried:
Used a Authorization header with value "Basic <base64 encoded string version of username:password>"
Added Content-Type header
Added mimetype header
Tried to use a third-party CFC
Nothing seems to work.
Jira's certificate configuration checks out fine, including their intermediate cert - you can confirm this with ssllabs or a similar tester, eg https://globalsign.ssllabs.com/analyze.html?d=jira.bullhorn.com .
In your case the reason you see a problem will be because you are using an old version of Coldfusion which is using an old JVM, which neither downloads their Digicert intermediate certificate, nor has that certificate pre-installed. Ideally you should be upgrading from CF11.
For a workaround you can manually install the Digicert intermediate certificate + Jira bullhorn certificate to your server's cacerts - instructions for this vary depending upon your environment but one example is https://helpx.adobe.com/coldfusion/kb/import-certificates-certificate-stores-coldfusion.html - then restart the CF service and retry the cfhttp call.
I am using google api with a test key
<cfhttp method="post" url="https://maps.googleapis.com/maps/api/geocode/xml?key=AIzaSyAoMhyMMfSvs1Z9xp9fNiBt9ogpryCQZNQ"
result="googlejson" throwonerror="true">
<cfhttpparam name="address" type="URL" value="1600+Amphitheatre+Parkway,+Mountain+View,+CA">
</cfhttp>
<cfdump var="#googlejson#" />
<cfabort>
"Connection Failure: Status code unavailable" occurred while running above code in local system but getting response from postman. I am using CF16.
Image
I got the following output when I ran the script in my local environment (CF2016).
It gave me desired output. So there should not be any error when you run it locally. I'm not sure what exactly you are looking for? Which version CF you are using?
I am working on a project that involves RESTful Api and I need to upload an attachment to another server and that server will give me response if my upload is successful or not. PS: They require us to use PUT to upload the attachment.
I can use cURL to fulfill this process:
curl -s -u "username:password" -H "accept: application/json" -F "attachment=#file_path" -X PUT https://example.com/MailManagement/ws/v3/send/message/attachment
But when I write it bycfhttp, the response is 200 OK, but their server would tell me
"Problem while parsing request"
I use cfhttpparam type="file",like below, it will say Problem while parsing request
<cffunction name="uploadAttachment" access="remote" description="Upload An Attachment">
<cfhttp url = "https://example.com/MailManagement/ws/v3/send/message/attachment" method="put" result="httpResp" username="username" password="password">
<cfhttpparam type="header" name="Content-Type" value="multipart/form-data">
<cfhttpparam type="file" file="C:\temp\1.txt" name="1.txt">
</cfhttp>
<cfset response_message = "#httpResp.tostring()#">
<cfreturn response_message>
</cffunction>
I have insert the certificate for the url and it works for other api calls, but not for the upload file one.
That company gives us example codes written in Unirest Java fairly simple.I will put their code here, my code and their code should do the same thing.
HttpResponse<JsonNode> response = Unirest.put("https://example.com/MailManagement/ws/v3/send/message/attachment")
.header("accept", "application/json")
.basicAuth("username", "password") // provide Direct address and password
.field("attachment", new File("")) // provide file to upload
.asJson();
JsonNode json = response.getBody(); // json response
I'm trying to download a file from Box.com through API using the following code.
<cfhttp url="https://api.box.com/2.0/files/(FILE_ID)/content/" method="GET" redirect="true" >
<cfhttpparam type="header" name="Authorization" value="Bearer (DEVELOPER_TOKEN)">
</cfhttp>
As per documentation it should return 302 Found as response. And redirects to dl.boxcloud.com for download. But I'm getting 200 as response.
Not sure why I'm getting 200 as response. I need to download the file through the API call. Did I missed anything?
With respect to #Miguel-F's comment, I've surfed and found a solution from Ben Nadel's post.
I've got 200 as response, this is because ColdFusion followed the redirect to dl.boxcloud.com (since by default, the REDIRECT attribute is TRUE), and the redirected request's response is 200.
Actually we should stop the redirect by setting REDIRECT attribute to FALSE. So that Coldfusion will return actual response to the invoking code.
So I've set REDIRECT attribute to FALSE.
<cfhttp url="https://api.box.com/2.0/files/(FILE_ID)/content/" method="GET" redirect="false" >
<cfhttpparam type="header" name="Authorization" value="Bearer (DEVELOPER_TOKEN)">
</cfhttp>
And now I'm getting 302 found as response as per the documentation.
With this response, we're having Location key (in which the code was redirected earlier) in the ResponseHeader. So by using the Location URL we can download the file using CFHEADER and CFCONTENT tags.
Reference : https://www.bennadel.com/blog/934-ask-ben-handling-redirects-with-coldfusion-cfhttp.htm
I'm implementing a web service using camel cxf to be deployed in Karaf.
I'm using the pax web that comes with karaf. I'm using the cxf codegen plugin in pom to do wsdl to java.
I'm defining the cxf uri and the routes in the RouteBuilder Java DSL. The blueprint.xml only has some beans and ref to the RouteBuilder.
final String cxfUri =
String.format("cxf:%s?serviceClass=%s&wsdlURL=wsdl/Event.wsdl",
"/Event.jws", com.example.EventPortType.class.getCanonicalName());
I have setup ssl with the pax-web(jetty.xml). If i send the WSSE security headers with username and password, it generates a MustUnderstand soap fault.
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" S:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Id-LdZa8aaGdy7mWQWXLp_zpbfg">
<wsse:Username>xxx</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">xxx</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
The input request cannot be changed.
I get this exception.
<soap:Fault>
<faultcode>soap:MustUnderstand</faultcode>
<faultstring>MustUnderstand headers: [{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood.</faultstring>
</soap:Fault>
How can i secure the cxf endpoint to authenticate the request?
Thank you.
you need to add a WSS4J interceptors to the exposed CXF service. You can provide your own PasswordCallback for the user validation, but I prefer to leverage the native JAAS. This is a blueprint example requiring the UsernameToken with any Karaf user (this is for exposing a camel-cxf routes, however the same principle applies to the pure CXF implementation). If you prefer Java based Camel route builders, you may add the interceptor beans to the context registry to use them. But - the blueprint (or spring config) allows you to more fine-grained control than simple endpoint parameters.
<?xml version="1.0" encoding="UTF-8"?>
<blueprint
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://cxf.apache.org/blueprint/core"
xmlns:camelcxf="http://camel.apache.org/schema/blueprint/cxf"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd http://camel.apache.org/schema/blueprint
http://camel.apache.org/schema/blueprint/camel-blueprint.xsd http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0
http://svn.apache.org/repos/asf/aries/trunk/blueprint/blueprint-cm/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.1.0.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
http://cxf.apache.org/blueprint/jaxws http://cxf.apache.org/schemas/blueprint/jaxws.xsd
http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/cxf/camel-cxf-2.7.5.xsd">
<bean id="authenticationInterceptor" class="org.apache.cxf.interceptor.security.JAASLoginInterceptor">
<property name="contextName" value="karaf"/>
<property name="roleClassifier" value="RolePrincipal"/>
<property name="roleClassifierType" value="classname"/>
</bean>
<bean id="wsSecInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<argument>
<map>
<entry key="action" value="UsernameToken"/>
<entry key="passwordType" value="PasswordText"/>
</map>
</argument>
</bean>
<!-- ================ Apache Camel impl ======================= -->
<camelcxf:cxfEndpoint id="testService2"
address="/api/2.0/external/TestService"
xmlns:apogado="http://test.ws.apogado.com/v1_0/ws"
endpointName="apogado:AddressServicePort"
serviceName="apogado:AddressService"
wsdlURL="classpath:/xsd/ws/TestService.wsdl"
>
<camelcxf:properties>
<entry key="dataFormat" value="PAYLOAD" />
<entry key="ws-security.ut.no-callbacks" value="true"/>
<entry key="ws-security.validate.token" value="false"/>
</camelcxf:properties>
<camelcxf:inInterceptors>
<ref component-id="wsSecInterceptor" />
<ref component-id="authenticationInterceptor"/>
</camelcxf:inInterceptors>
<camelcxf:features>
</camelcxf:features>
</camelcxf:cxfEndpoint>
<camelContext xmlns="http://camel.apache.org/schema/blueprint" id="testWsCtx" trace="true">
<!-- your service implementation -->
<route>
<from uri="testService2" />
<to uri="..." />
<route>
</camelContext>
</blueprint>