我正在尝试实施Amadeus Soap4网络服务。按照“实施”文档的建议创建了标题条目。但总是收到 12 |演示文稿| Soap消息头不正确错误。我在SOAP UI中尝试了生成的soap头,它可以在不对其进行任何更改的情况下工作。所以我正在寻找一种解决方案来解决应用程序中发生的问题。
答案 0 :(得分:0)
在OpenEdge中实施WS-Security时需要采取几个步骤,因为基本上没有任何内置支持!
首先,您需要能够创建密码摘要。这里有几个缺陷要避免(不同类型的字符集之间的字符转换,处理二进制数据等)。
此过程将指向“Nonce”,日期和密码并返回“摘要”。
PROCEDURE generatePasswordDigest :
DEFINE INPUT PARAMETER mNonce AS MEMPTR NO-UNDO.
DEFINE INPUT PARAMETER pcCreated AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER pcPassword AS CHARACTER NO-UNDO.
DEFINE OUTPUT PARAMETER pcHash AS CHARACTER NO-UNDO.
DEFINE VARIABLE mBytes AS MEMPTR NO-UNDO.
DEFINE VARIABLE mSHA1 AS MEMPTR NO-UNDO.
/*
Set size of mempointer, created + 36 because of all data that should fit.
*/
SET-SIZE(mBytes) = 36 + LENGTH(pcCreated).
/* Put the decoded nonce first */
PUT-BYTES(mBytes, 1) = mNonce.
/* Add create time */
PUT-STRING(mBytes, 1 + 16) = pcCreated.
/* Set SHA1 returns a 20 byte raw string. */
SET-SIZE(mSHA1) = 20.
mSHA1 = SHA1-DIGEST(pcPassword).
/* Add password, SHA1-digested (so we need to put bytes instead of a string */
PUT-BYTES(mBytes, 17 + LENGTH(pcCreated)) = mSHA1.
/* Create out-data in B64-encoded format */
pcHash = STRING(BASE64-ENCODE(SHA1-DIGEST(mBytes))).
/* Clean up mempointers */
SET-SIZE(mBytes) = 0.
SET-SIZE(mSHA1) = 0.
SET-SIZE(mNonce) = 0.
END PROCEDURE.
获得摘要后,您必须完成将SOAP-header放在一起的相当大的工作。最有可能是更有效的方法,你可以创建程序,以更加模块化的方式编码等等。但这实际上是有效的。不用说,你需要在下面做出很多改变。至少所有“XXXYYY”都应根据您的需求进行定制。
PROCEDURE setRequestSessionHeader :
DEFINE OUTPUT PARAMETER phHeader AS HANDLE.
DEFINE INPUT PARAMETER pcNamespace AS CHARACTER.
DEFINE INPUT PARAMETER pcLocalNS AS CHARACTER.
DEFINE OUTPUT PARAMETER plDeleteOnDone AS LOGICAL.
DEFINE VARIABLE hSoapHeaderEntryref1 AS HANDLE NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref2 AS HANDLE NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref3 AS HANDLE NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref4 AS HANDLE NO-UNDO.
DEFINE VARIABLE hSoapHeaderEntryref5 AS HANDLE NO-UNDO.
DEFINE VARIABLE hXDocument AS HANDLE NO-UNDO.
DEFINE VARIABLE hOASSecurity AS HANDLE NO-UNDO.
DEFINE VARIABLE hOASUsernameToken AS HANDLE NO-UNDO.
DEFINE VARIABLE hOASUserName AS HANDLE NO-UNDO.
DEFINE VARIABLE hOASPassword AS HANDLE NO-UNDO.
DEFINE VARIABLE hOASPasswordType AS HANDLE NO-UNDO.
DEFINE VARIABLE hOASNonce AS HANDLE NO-UNDO.
DEFINE VARIABLE hWSUCreated AS HANDLE NO-UNDO.
DEFINE VARIABLE hADDMessageID AS HANDLE NO-UNDO.
DEFINE VARIABLE hADDTo AS HANDLE NO-UNDO.
DEFINE VARIABLE hADDAction AS HANDLE NO-UNDO.
DEFINE VARIABLE hAMA_SecurityHostedUser AS HANDLE NO-UNDO.
DEFINE VARIABLE hUserId AS HANDLE NO-UNDO.
DEFINE VARIABLE hTxt AS HANDLE NO-UNDO.
DEFINE VARIABLE hAttr AS HANDLE NO-UNDO.
DEFINE VARIABLE hRootNode AS HANDLE NO-UNDO.
/* Namespaces */
DEFINE VARIABLE cNSAddressing AS CHARACTER NO-UNDO.
DEFINE VARIABLE cNSSecurity AS CHARACTER NO-UNDO.
DEFINE VARIABLE cNSSecurityUtils AS CHARACTER NO-UNDO.
DEFINE VARIABLE cNSAmaSec AS CHARACTER NO-UNDO.
DEFINE VARIABLE cMessageId AS CHARACTER NO-UNDO.
DEFINE VARIABLE cUserName AS CHARACTER NO-UNDO.
DEFINE VARIABLE cPasswordClear AS CHARACTER NO-UNDO.
DEFINE VARIABLE cPasswordDigest AS CHARACTER NO-UNDO.
DEFINE VARIABLE cCreated AS CHARACTER NO-UNDO.
DEFINE VARIABLE cAction AS CHARACTER NO-UNDO.
DEFINE VARIABLE cTo AS CHARACTER NO-UNDO.
DEFINE VARIABLE cNonceB64 AS CHARACTER NO-UNDO.
DEFINE VARIABLE cOfficeId AS CHARACTER NO-UNDO.
DEFINE VARIABLE mNonce AS MEMPTR NO-UNDO.
/* Changes might be needed here depending on what service is called */
ASSIGN
cNSAddressing = "http://www.w3.org/2005/08/addressing"
cNSSecurity = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
cNSSecurityUtils = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
cNSAmaSec = "http://xml.amadeus.com/2010/06/Security_v1"
cAction = "http://webservices.amadeus.com/XXXYYY"
cTo = "https://noded1.production.webservices.amadeus.com/XXXYYY".
/* Set your username, office ID and password */
ASSIGN
cUserName = "XXXYYY"
cOfficeId = "XXXYYY"
cPasswordClear = "XXXYYY".
/* Delete header when done! */
ASSIGN
plDeleteOnDone = TRUE.
CREATE SOAP-HEADER ghSoapHeader.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref1.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref2.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref3.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref4.
CREATE SOAP-HEADER-ENTRYREF hSoapHeaderEntryref5.
CREATE X-DOCUMENT hXDocument.
CREATE X-NODEREF hRootNode.
CREATE X-NODEREF hOASSecurity.
CREATE X-NODEREF hTxt.
CREATE X-NODEREF hOASUsernameToken.
CREATE X-NODEREF hOASPassword.
CREATE X-NODEREF hOASUserName.
CREATE X-NODEREF hOASNonce.
CREATE X-NODEREF hADDMessageID.
CREATE X-NODEREF hADDTo.
CREATE X-NODEREF hADDAction.
CREATE X-NODEREF hWSUCreated.
CREATE X-NODEREF hAMA_SecurityHostedUser.
CREATE X-NODEREF hUserId.
/* Not DATETIME-TZ! */
DEFINE VARIABLE dtZuluNow AS DATETIME NO-UNDO.
/* Genereate a random key and base64-encode it */
SET-SIZE(mNonce) = 16.
mNonce = GENERATE-RANDOM-KEY.
cNonceB64 = BASE64-ENCODE(mNonce).
/* Get time in UTC/GMT/ZULU/Timezone 0 */
dtZuluNow = DATETIME-TZ(NOW,0).
/* Manipulate the date string to fit specs... */
ASSIGN
cMessageId = LC(SUBSTRING(STRING(GENERATE-UUID), 8, 20))
cCreated = STRING(dtZuluNow, "9999-99-99THH:MM:SS") + ":000Z".
/* Genereate digest */
RUN generatePasswordDigest( mNonce, cCreated, cPasswordClear, OUTPUT cPasswordDigest).
/* Root node */
hXDocument:CREATE-NODE-NAMESPACE(hRootNode, "", "root", "element").
hXDocument:INSERT-BEFORE(hRootNode, ?).
/**** Addressing ****/
/* MessageID */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref1).
hXDocument:CREATE-NODE-NAMESPACE(hADDMessageID, cNSAddressing, "MessageID", "ELEMENT").
hRootNode:APPEND-CHILD(hAddMessageID).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cMessageId.
hADDMessageId:APPEND-CHILD(hTxt).
hSoapHeaderEntryref1:SET-NODE(hADDMessageID).
/* Action */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref2).
hXDocument:CREATE-NODE-NAMESPACE(hADDAction, cNSAddressing, "Action", "ELEMENT").
hRootNode:APPEND-CHILD(hADDAction).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cAction.
hADDAction:APPEND-CHILD(hTxt).
hSoapHeaderEntryref2:SET-NODE(hADDAction).
/* To */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref3).
hXDocument:CREATE-NODE-NAMESPACE(hADDTo, cNSAddressing, "To", "ELEMENT").
hRootNode:APPEND-CHILD(hADDTo).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cTo.
hADDTo:APPEND-CHILD(hTxt).
hSoapHeaderEntryref3:SET-NODE(hADDTo).
/**** Security ****/
/* Root node */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref4).
hXDocument:CREATE-NODE-NAMESPACE(hOASSecurity, cNSSecurity, "Security", "ELEMENT").
hRootNode:APPEND-CHILD(hOASSecurity).
/* UserNameToken node */
hXDocument:CREATE-NODE-NAMESPACE(hOASUsernameToken, cNSSecurity, "UsernameToken", "ELEMENT").
hOASUsernameToken:SET-ATTRIBUTE("Id", "UsernameToken-1").
hOASSecurity:INSERT-BEFORE(hOASUsernameToken, ?).
/* Username */
hXDocument:CREATE-NODE-NAMESPACE(hOASUserName, cNSSecurity, "Username", "ELEMENT").
hRootNode:APPEND-CHILD(hOASUserName).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cUserName.
hOASUserName:APPEND-CHILD(hTxt).
hOASUsernameToken:APPEND-CHILD(hOASUserName).
/* Nonce */
hXDocument:CREATE-NODE-NAMESPACE(hOASNonce, cNSSecurity, "Nonce", "ELEMENT").
hOASNonce:SET-ATTRIBUTE("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary").
hOASUsernameToken:APPEND-CHILD(hOASNonce).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cNonceB64.
hOASNonce:APPEND-CHILD(hTxt).
/* Password hash */
hXDocument:CREATE-NODE-NAMESPACE(hOASPassword, cNSSecurity, "Password", "ELEMENT").
hOASPassword:SET-ATTRIBUTE("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest").
hOASUsernameToken:APPEND-CHILD(hOASPassword).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cPasswordDigest.
hOASPassword:APPEND-CHILD(hTxt).
/* Created - timestamp */
hXDocument:CREATE-NODE-NAMESPACE(hWSUCreated, cNSSecurityUtils, "Created", "ELEMENT").
hOASUsernameToken:APPEND-CHILD(hWSUCreated).
hXDocument:CREATE-NODE(hTxt, "", "TEXT").
hTxt:NODE-VALUE = cCreated.
hWSUCreated:APPEND-CHILD(hTxt).
hSoapHeaderEntryref4:SET-NODE(hOASSecurity).
/**** AMA_SecurityHostedUser ****/
/* Root node */
ghSoapHeader:ADD-HEADER-ENTRY(hSoapHeaderEntryref5).
hXDocument:CREATE-NODE-NAMESPACE(hAMA_SecurityHostedUser, cNSAMASec, "AMA_SecurityHostedUser", "ELEMENT").
hRootNode:APPEND-CHILD(hAMA_SecurityHostedUser).
/* UserID */
hXDocument:CREATE-NODE-NAMESPACE(hUserID, cNSAMASec, "UserID", "ELEMENT").
hUserID:SET-ATTRIBUTE("AgentDutyCode", "SU").
hUserID:SET-ATTRIBUTE("RequestorType", "U").
hUserID:SET-ATTRIBUTE("PseudoCityCode", cOfficeId).
hUserID:SET-ATTRIBUTE("POS_Type", "1").
hAMA_SecurityHostedUser:APPEND-CHILD(hUserID).
hSoapHeaderEntryref5:SET-NODE(hAMA_SecurityHostedUser).
/* Output the header */
phHeader = ghSoapHeader.
/* Cleanup */
IF VALID-HANDLE(hOASSecurity) THEN
DELETE OBJECT hOASSecurity.
IF VALID-HANDLE(hOASUsernameToken) THEN
DELETE OBJECT hOASUsernameToken.
IF VALID-HANDLE(hOASUserName) THEN
DELETE OBJECT hOASUserName.
IF VALID-HANDLE(hOASPassword) THEN
DELETE OBJECT hOASPassword.
IF VALID-HANDLE(hADDMessageID) THEN
DELETE OBJECT hADDMessageID.
IF VALID-HANDLE(hOASNonce) THEN
DELETE OBJECT hOASNonce.
IF VALID-HANDLE(hTxt) THEN
DELETE OBJECT hTxt.
IF VALID-HANDLE(hADDTo) THEN
DELETE OBJECT hADDTo.
IF VALID-HANDLE(hWSUCreated) THEN
DELETE OBJECT hWSUCreated.
IF VALID-HANDLE(hADDAction) THEN
DELETE OBJECT hADDAction.
IF VALID-HANDLE(hXDocument) THEN
DELETE OBJECT hXDocument.
IF VALID-HANDLE(hRootNode) THEN
DELETE OBJECT hRootNode.
IF VALID-HANDLE(hSoapHeaderEntryRef1) THEN
DELETE OBJECT hSoapHeaderEntryRef1.
IF VALID-HANDLE(hSoapHeaderEntryRef2) THEN
DELETE OBJECT hSoapHeaderEntryRef2.
IF VALID-HANDLE(hSoapHeaderEntryRef3) THEN
DELETE OBJECT hSoapHeaderEntryRef3.
IF VALID-HANDLE(hSoapHeaderEntryRef4) THEN
DELETE OBJECT hSoapHeaderEntryRef4.
IF VALID-HANDLE(hSoapHeaderEntryRef5) THEN
DELETE OBJECT hSoapHeaderEntryRef5.
IF VALID-HANDLE(hAMA_SecurityHostedUser) THEN
DELETE OBJECT hAMA_SecurityHostedUser.
IF VALID-HANDLE(hUserId) THEN
DELETE OBJECT hUserId.
END PROCEDURE.
最后,在调用实际的Web服务之前,您需要附上上面的过程,以便动态创建标题:
XXXYYY-handle:SET-CALLBACK-PROCEDURE( "REQUEST-HEADER", "setRequestSessionHeader" ).
基本上应该是它。一个粗略的例子,但可能不是很漂亮...
答案 1 :(得分:0)
这是由于Amadeus的网络服务URL。请确保网络请求的网址与“add:To”标记的值相匹配,包括字母大小写。请求将以小写形式发送到地址,如 noded1 ,而不是 nodeD1 强>
供参考,请参阅以下链接 Amadeus webservice address point Issue