Forum Post: How do I connect an SSL secured Web Service

Status
Not open for further replies.
G

Gunnar.Vogt

Guest
Hi, I'm having trouble to connect to 3rd-party web service (this service is stable and works with PHP and Java clients just fine). My ABLcode (OpenEdge 10.2) generates the error: "HTTP Status 500 - Request processing failed; nested exception is org.springframework.ws.soap.saaj.SaajSoapMessageException: Could not access envelope: Unable to create envelope from given source: ; nested exception is com.sun.xml.messaging.saaj.SOAPExceptionImpl: Unable to create envelope from given source:" This code derived from multiple sources and is my first attempt to access a Web Service via a secured SOAP connection. I hope someone in our community is able to see my mistake(s). FYI: At the moment I'm using FIDDLER to generate a proxy that can track the secured communication between my client and the server. This seems to be the only solution so far to trap any valuable error messages from the server. Thanks, Gunnar define variable hWebService as handle no-undo. define variable hSERVICE as handle no-undo. define variable ierror as integer no-undo. define variable cerror as character no-undo. define variable ghHeader as handle no-undo. define variable iParam as character no-undo init '###########'. define variable oParam as logical no-undo. /*---------------------------------------------------------------------------*/ /* MAIN */ /*---------------------------------------------------------------------------*/ do on error undo, throw: /*-------------------------------------------------------------------------*/ /* Connect to Web Service */ /*-------------------------------------------------------------------------*/ /* Build global SOAP request header containing UsernameToken element */ run BuildRequestHeader (output ghHeader). /* connect to Web Service and get WSDL */ create server hWebService. hWebService:connect("-WSDL 'https://###############.wsdl' -nohostverify"). run SERVICE set hSERVICE on hWebService. /* Associate the request callback with the service port */ hSERVICE:set-callback-procedure ("REQUEST-HEADER", "ReqHandler"). /* hSERVICE:set-callback-procedure ("RESPONSE-HEADER", "ResHandler"). */ /*-------------------------------------------------------------------------*/ /* Call Web Service */ /*-------------------------------------------------------------------------*/ /* !!!!! now the trouble starts. !!!!!! */ run proc######### in hSERVICE (iParam, output oParam). message value1 view-as alert-box. /*-------------------------------------------------------------------------*/ /* Error Handling */ /*-------------------------------------------------------------------------*/ catch mySoapErrorObject as progress.lang.soapfaulterror: do ierror = 1 to mysoaperrorobject:nummessages: cerror = cerror + substitute ('[soap &1] &2', ierror, mysoaperrorobject:getmessage(ierror)) + "~n". end. delete object mysoaperrorobject. end catch. catch mySystemErrorObject as progress.lang.syserror: do ierror = 1 to mySystemErrorObject:nummessages: cerror = cerror + substitute ('system [&1] &2', ierror, mySystemErrorObject:getmessage(ierror)) + "~n". end. delete object mySystemErrorObject. end catch. finally: delete procedure hSERVICE no-error. hWebService:disconnect() no-error. delete object hWebService no-error. if cerror "" then message "errors occured:" skip cerror view-as alert-box error. end. /* finally */ end. /*---------------------------------------------------------------------------*/ /* Service Definitions */ /*---------------------------------------------------------------------------*/ PROCEDURE proc#########: DEFINE INPUT PARAMETER iParam AS CHARACTER NO-UNDO. DEFINE OUTPUT PARAMETER oParam AS LOGICAL NO-UNDO. END PROCEDURE. /*---------------------------------------------------------------------------*/ /* Supporting Procedures */ /*---------------------------------------------------------------------------*/ procedure ReqHandler: /*----------------------------------------------------------------------------*/ /* Purpose: Build Security SOAP header */ /* Parameters: hHeader: handle for the x-document */ /* */ /* Notes: OpenEdge® Development Web service dvwsv.pdf */ /*----------------------------------------------------------------------------*/ define output parameter hHeader as handle. define input parameter cNamespace as character. define input parameter cLocalNS as character. define output parameter lDeleteOnDone as logical. /* The IF test determines if this is the first request. If it is, then g_ghHeader is not set and hHeader is set to ? to ensure that no header is sent. ghHeader gets set when the response header is returned, so a subsequent pass through this code takes the previous response header and sends it as the current request header. */ if valid-handle (ghHeader) then assign hHeader = ghHeader lDeleteOnDone = no . else /* first response */ assign hHeader = ? lDeleteOnDone = yes . end procedure. procedure ResHandler: /*----------------------------------------------------------------------------*/ /* Purpose: Build Security SOAP header */ /* Parameters: hHeader: handle for the x-document */ /* */ /* Notes: OpenEdge® Development Web service dvwsv.pdf */ /*----------------------------------------------------------------------------*/ define input parameter hHeader as handle. define input parameter cNamespace as character. define input parameter cLocalNS as character. message 'RESPONSE ResHandler' skip cNamespace skip cLocalNS skip valid-handle (hHeader) skip valid-handle (ghHeader) view-as alert-box. /* If the g_header global variable is valid coming in, it has already been set in a previous response, therefore, delete the unnecessary response header object. Otherwise, set g-header to the response header object to pass back to the request header handler on subsequent requests. */ if valid-handle (ghHeader) then delete object hHeader. else ghHeader = hHeader. /* first response */ end procedure. procedure BuildRequestHeader: /*----------------------------------------------------------------------------*/ /* Purpose: Build Security SOAP header */ /* Parameters: hHeader: handle for the x-document */ /* */ /* Notes: http://knowledgebase.progress.com/articles/Article/P140169?popup=true */ /*----------------------------------------------------------------------------*/ define output parameter hHeader as handle. define variable cUsername as character init '##########':U no-undo. /* user name not encrypted */ define variable cPassword as character init '##########':U no-undo. /* password encrypted */ define variable cNonce as character no-undo. /* UUID encrypted in multiple of 4 bytes 'N2RkYmMxODgxMTY0N2EzNWJiZjA':U */ define variable cCreated as character no-undo. /* '2012-03-06T10:09:47Z':U */ define variable rawTemp as raw no-undo. define variable lcBuiltHeader as longchar no-undo. define variable hHeaderEntryRef as handle no-undo. define variable cClientNS as character init 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd':U no-undo. define variable hXDoc as handle no-undo. define variable hXNodeSec as handle no-undo. define variable hXNodeUNT as handle no-undo. define variable hXUsername as handle no-undo. define variable hXPassword as handle no-undo. define variable hXNonce as handle no-undo. define variable hXCreated as handle no-undo. /* timestamp of authentication Format : Year (yyyy), “-”, month (mm), “-”, day (dd), “T”, hour (hh 24h), “:”, minutes (mm), “:”, seconds (ss), “Z” time zone: UTC e.g. : 2012-03-06T10:55:17Z) */ assign cCreated = string (datetime-tz (now,0)) /* '10/18/2014 23:04:50.541+00:00' */ cCreated = substitute ('&1-&2-&3T&4Z':U, substring (cCreated, 7, 4), substring (cCreated, 1, 2), substring (cCreated, 4, 2), substring (cCreated, 12, 8)) . /* “Nonce” value - random unique value - e.g. UUID) - must be multiple of 4 Bytes - in WSSE-Element the “Nonce” value is base64 crypted PHP code $uuid = uniqid( $prefix.'_', true); $uuid_md5 = md5( $uuid); $binary_nonce = substr( $uuid_md5, 0, 20); assign rawTemp = 'TEST' + generate-uuid rawTemp = md5-digest (rawTemp) /* result is 16Byte raw */ cNonce = base64-encode (rawTemp) . */ cNonce = substring (base64-encode (md5-digest (generate-uuid)), 1, 28). /* passwort is base64 crypted we need SHA1 Hash of binary „Nonce“ + timestamp + password PHP $ rawDigest = $binary_nonce.$timestamp.$password; $sha1 = sha1( $rawDigest, true); $digest = base64_encode( sha1); */ cPassword = base64-encode (sha1-digest ( cNonce + cCreated + cPassword)). /* Build XML */ create x-document hXDoc . create x-noderef hXNodeSec . create x-noderef hXNodeUNT . create x-noderef hXUsername. create x-noderef hXPassword. create x-noderef hXNonce . create x-noderef hXCreated . create soap-header hHeader. create soap-header-entryref hHeaderEntryRef. hHeader:add-header-entry(hHeaderEntryRef). hXDoc:CREATE-NODE-NAMESPACE (hXNodeSec, cClientNS, 'wsse:Security':U, 'ELEMENT':U). hXNodeSec:SET-ATTRIBUTE ('xmlns:wsu':U, 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd':U). hXDoc:CREATE-NODE-NAMESPACE (hXNodeUNT, cClientNS, 'wsse:UsernameToken':U, 'ELEMENT':U). hXNodeUNT:SET-ATTRIBUTE ('xmlns:wsu':U, 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd':U). hXDoc:INSERT-BEFORE(hXNodeSec, ?). run yInsertXMLTextNode (hXDoc, hXNodeUNT, 'wsse:Username':U, cUsername, input-output hXUsername). run yInsertXMLTextNode (hXDoc, hXNodeUNT, 'wsse:password':U, cPassword, input-output hXPassword). hXPassword:SET-ATTRIBUTE ('Type':U, 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest':U). run yInsertXMLTextNode (hXDoc, hXNodeUNT, 'wsse:Nonce':U, cNonce , input-output hXNonce ). hXNonce:SET-ATTRIBUTE ('EncodingType':U, 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary':U). run yInsertXMLTextNode (hXDoc, hXNodeUNT, 'wsu:Created':U, cCreated , input-output hXCreated ). hXCreated:SET-ATTRIBUTE ("xmlns:wsu", 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd':U). hXNodeSec:APPEND-CHILD (hXNodeUNT). /* Fill the header entry using a deep copy */ hHeaderEntryRef:set-node (hXNodeSec). hHeaderEntryRef:set-must-understand (yes). /* save the XML for debugging */ hXDoc:save ('file':U, 'c:\temp\header_ws-security_output.xml':U). finally: delete object hHeaderEntryRef no-error. delete object hXDoc no-error. delete object hXNodeSec no-error. delete object hXNodeUNT no-error. delete object hXUsername no-error. delete object hXPassword no-error. delete object hXNonce no-error. delete object hXCreated no-error. end. /* finally */ end procedure. PROCEDURE yInsertXMLTextNode PRIVATE : /*----------------------------------------------------------------------------*/ /* Purpose: Insert an XML Textnode in a specified parent node */ /* Parameters: phDocument: handle for the x-document */ /* phParent : parent of the node created by this procedure */ /* pcLabel : name of the new node */ /* pcText : text contained in the new node */ /* phThisNode: handle of the newly created XML node */ /*----------------------------------------------------------------------------*/ define input parameter phDocument as handle no-undo. define input parameter phParent as handle no-undo. define input parameter pcLabel as char no-undo. define input parameter pcText as char no-undo. define input-output parameter phThisNode as handle no-undo. define variable hChild2 as handle no-undo. Main: do on error undo Main, leave Main: create x-noderef hChild2. phDocument:create-node(phThisNode,pcLabel,'Element':U). phParent:append-child(phThisNode). phDocument:create-node(hChild2,?,'Text':U). phThisNode:append-child(hChild2). hChild2:node-value = (if pcText = ? then '?':U else pcText). return. end. /*Main:*/ return error. finally: delete object hChild2 no-error. end. /* finally */ END PROCEDURE.

Continue reading...
 
Status
Not open for further replies.
Top