使用ColdFusion创建安全的Web服务

pet*_*ron 7 security coldfusion ws-security wsdl web-services

我使用ColdFusion创建了一个使用内联身份验证的Web服务的现有API,但我想使用某种身份验证来保护它,但我无从何处开始.

ColdFusion通过在我的cfcs末尾添加?wsdl来自动生成Web服务.

当我说""我的意思是,对于每个Web服务调用,客户端必须传入soapenv:body中的密钥/传递,如下所示:

<apiKey xsi:type="xsd:string">test</apiKey>
<apiPass xsi:type="xsd:string">test!ng</apiPass>
Run Code Online (Sandbox Code Playgroud)

但我想我想使用WS-Security或基本身份验证,但我不知道我在做什么.

似乎没有人在CF社区做我想问的事情,这似乎很奇怪.

Cia*_*her 4

一般来说,我不喜欢 WSE (http://oasis-open.org/) 或 SOAP,但它在集成情况下很有用,例如,我们在使用 .NET Web 服务时就使用过它。

我的偏好是使用Application.cfc与 Web 服务相同的目录,通过 IP 和安全令牌或用户名/密码来验证请求。我们将其用于其他人使用的 RESTful Web 服务。或者,您可以将身份验证代码作为 Web 服务处理本身的一部分。

如果必须使用 WSE,则需要addSOAPRequestHeader()在发送 SOAP 数据包时添加一堆 SOAP 标头,然后在获取响应时检查这些相同的标头。这可能很混乱,但这里有一些适合我们的代码:

<cffunction name="AddSecurityHeaders" access="public" returntype="any" hint="This adds the security headers as defined in the WS Security section of the WSS standard. Username and password are unencrypted." output="Yes">
        <cfargument name="webSvc" required="Yes" type="any" hint="This must be a vaild web service."> 
        <cfargument name="username" required="Yes" type="string" hint="Username required by webservice being called."> 
        <cfargument name="password" required="Yes" type="string" hint="Password required by web service being called."> 
        <cfargument name="action" required="Yes" type="string" hint="Value to be inseted into wsa:Action node."> 
        <cfargument name="to" required="Yes" type="string" hint="Value to be inseted into wsa:To node."> 
        <cfargument name="mustUnderstandSecurityHdr" required="No" type="boolean" default="false" hint="This value will be inserted into the <wsse:Security> header as the 'mustUnderstand' value."> 

        <cfscript>

        var rightNow = "" ;
        var expiryTime = "" ;
        var objXmlAction = "" ;
        var objXmlMessageID = "" ;
        var objXmlTo = "" ;
        var objXmlSecurity = "" ;
        var objXmlReplyTo = "" ;
        var objTimezone = CreateObject("component", "com.utils.timezone") ;

        // Setup times (UTC/GMT only!)
        rightNow = objTimezone.castToUTC(Now()) ;
        expiryTime = DateAdd("n", 5, rightNow) ;

        // Create XML doument and add required nodes starting with <wsa:Action>
        objXmlAction = XmlNew() ;
        objXmlAction.XmlRoot = XmlElemNew(objXmlAction,  "http://schemas.xmlsoap.org/ws/2004/03/addressing", "wsa:Action") ;
        objXmlAction.XmlRoot.XmlText = ARGUMENTS.action ;

        // ..then <wsa:MessageID>
        objXmlMessageID = XmlNew() ;
        objXmlMessageID.XmlRoot = XmlElemNew(objXmlMessageID,  "http://schemas.xmlsoap.org/ws/2004/03/addressing", "wsa:MessageID") ;
        objXmlMessageID.XmlRoot.XmlText = "uuid:" & CreateUUID() ;

        // ...then <wsa:Address>
        objXmlReplyTo = XmlNew() ;
        objXmlReplyTo.XmlRoot = XmlElemNew(objXmlReplyTo,  "http://schemas.xmlsoap.org/ws/2004/03/addressing", "wsa:ReplyTo") ;
        objXmlReplyTo.XmlRoot.XMLChildren[1] = XmlElemNew(objXmlReplyTo,  "wsa:Address") ;
        objXmlReplyTo.XmlRoot.XMLChildren[1].XmlText = "http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous" ;

        // ..then <wsa:To>
        objXmlTo = XmlNew() ;
        objXmlTo.XmlRoot = XmlElemNew(objXmlTo,  "http://schemas.xmlsoap.org/ws/2004/03/addressing", "wsa:To") ;
        objXmlTo.XmlRoot.XmlText = ARGUMENTS.to ;

        // ..then the main <wsse:Security> node which contains further info...
        objXmlSecurity = XmlNew(true) ;
        objXmlSecurity.XmlRoot = XmlElemNew(objXmlSecurity,  "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "wsse:Security") ;
        // ...note: this namespace is added as it is used in children nodes and this can help avoid XmlSearch errors in CFMX
        //StructInsert(objXmlSecurity.XmlRoot.XmlAttributes, "xmlns:wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd") ;

         // ...Timestamp, it's children and attributes
        objXmlSecurity.XmlRoot.XMLChildren[1] = XmlElemNew(objXmlSecurity,  "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "wsu:Timestamp") ;
        StructInsert(objXmlSecurity.XmlRoot.XMLChildren[1].XmlAttributes, "wsu:Id", "Timestamp-#CreateUUID()#") ;

        objXmlSecurity.XmlRoot.XMLChildren[1].XmlChildren[1] = XmlElemNew(objXmlSecurity, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "wsu:Created") ;
        objXmlSecurity.XmlRoot.XMLChildren[1].XmlChildren[1].XmlText = DateFormat(rightNow, "YYYY-MM-DD") & "T" & TimeFormat(rightNow, "HH:mm:ss") & "Z" ;
        objXmlSecurity.XmlRoot.XMLChildren[1].XmlChildren[2] = XmlElemNew(objXmlSecurity, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "wsu:Expires") ;
        objXmlSecurity.XmlRoot.XMLChildren[1].XmlChildren[2].XmlText = DateFormat(expiryTime, "YYYY-MM-DD") & "T" & TimeFormat(expiryTime, "HH:mm:ss") & "Z" ;
        // ...Username token, attributes and children 
        objXmlSecurity.XmlRoot.XMLChildren[2] = XmlElemNew(objXmlSecurity,  "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "wsse:UsernameToken") ;
        StructInsert(objXmlSecurity.XmlRoot.XMLChildren[2].XmlAttributes, "xmlns:wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd") ;
        StructInsert(objXmlSecurity.XmlRoot.XMLChildren[2].XmlAttributes, "wsu:Id", "SecurityToken-#CreateUUID()#") ;
        // ...UsernameToken.Username
        objXmlSecurity.XmlRoot.XMLChildren[2].XmlChildren[1] = XmlElemNew(objXmlSecurity, "wsse:Username") ;
        objXmlSecurity.XmlRoot.XMLChildren[2].XmlChildren[1].XmlText = Trim(ARGUMENTS.username) ;
        // ...UsernameToken.Password 
        objXmlSecurity.XmlRoot.XMLChildren[2].XmlChildren[2] = XmlElemNew(objXmlSecurity, "wsse:Password") ;
        StructInsert(objXmlSecurity.XmlRoot.XMLChildren[2].XmlChildren[2].XmlAttributes, "Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0##PasswordText") ; 
        objXmlSecurity.XmlRoot.XMLChildren[2].XmlChildren[2].XmlText = Trim(ARGUMENTS.password) ;
        // ... Nonce 
        objXmlSecurity.XmlRoot.XMLChildren[2].XmlChildren[3] = XmlElemNew(objXmlSecurity, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "wsse:Nonce") ;
        objXmlSecurity.XmlRoot.XMLChildren[2].XmlChildren[3].XmlText = ToBase64(CreateUUID()) ;
        // ...Created 
        objXmlSecurity.XmlRoot.XMLChildren[2].XmlChildren[4] = XmlElemNew(objXmlSecurity, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "wsu:Created") ;
        objXmlSecurity.XmlRoot.XMLChildren[2].XmlChildren[4].XmlText = DateFormat(rightNow, "YYYY-MM-DD") & "T" & TimeFormat(rightNow, "HH:mm:ss") & "Z" ;

        // Add the created headers to the soap requests - note that the 2nd and 3rd parameters have no significance in this instance
        addSOAPRequestHeader(ARGUMENTS.webSvc, "sia1", "hd1", "#objXmlAction#", false) ;
        addSOAPRequestHeader(ARGUMENTS.webSvc, "sia1", "hd1", "#objXmlMessageID#", false) ;
        addSOAPRequestHeader(ARGUMENTS.webSvc, "sia1", "hd1", "#objXmlReplyTo#", false) ;
        addSOAPRequestHeader(ARGUMENTS.webSvc, "sia1", "hd1", "#objXmlTo#", false) ;
        addSOAPRequestHeader(ARGUMENTS.webSvc, "sia1", "hd1", "#objXmlSecurity#", ARGUMENTS.mustUnderstandSecurityHdr) ;

        return ARGUMENTS.webSvc ;

        </cfscript>

    </cffunction>
Run Code Online (Sandbox Code Playgroud)

这是一个使用示例:

// Create web service
objWebSvc = CreateObject("webservice", "remoteWebService?WSDL") ;

// Create security object and add the security header to our SOAP request
objWSESecurity = CreateObject("component", "wse") ;

objWebSvc = objWSESecurity.AddSecurityHeaders(
    webSvc=objWebSvc,
    username="xxx", 
    password="yyy", 
    action="remoteAction", 
    to="remoteWebService", 
    mustUnderstandSecurityHdr=false
) ;
Run Code Online (Sandbox Code Playgroud)

你看 - 很多代码:)希望它能有所帮助。