coldfusion从salesforce获取API令牌-授予无效

coldfusion从salesforce获取API令牌-授予无效,coldfusion,salesforce,Coldfusion,Salesforce,我过得很糟糕…我正试图让coldfusion从salesforce获得代币,但我遇到了以下错误 {"error":"invalid_grant","error_description":"authentication failure"} 我试过cfscript local.http = new Http(url='https://test.salesforce.com/services/oauth2/token',method='post'); local.http.addPar

我过得很糟糕…我正试图让coldfusion从salesforce获得代币,但我遇到了以下错误

{"error":"invalid_grant","error_description":"authentication failure"}
我试过cfscript

local.http = new Http(url='https://test.salesforce.com/services/oauth2/token',method='post');

      local.http.addParam(type='header',name='content-type',   value='application/x-www-form-urlencoded');
      local.http.addParam(type='formField',name='grant_type',   value='password');
      local.http.addParam(type='formField',name='client_id',    value='client_id');
      local.http.addParam(type='formField',name='client_secret',  value='client_password_string');
      local.http.addParam(type='formField',name='username',   value='user@email.com');
      local.http.addParam(type='formField',name='password',   value='userspassword');
      local.http.addParam(type='formField',name='format',     value='json');

      local.httpSendResult = local.http.send();
      rc.httpResult = httpSendResult.getPrefix();
我试过cfhttp标签

<cfhttp url="https://test.salesforce.com/services/oauth2/token" method="POST">
         <cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded" />
         <cfhttpparam type="formField" name="grant_type" value="password" />

         <cfhttpparam type="formField" name="client_id" value="client_id" />
         <cfhttpparam type="formField" name="client_secret" value="client_password_string" />
         <cfhttpparam type="formField" name="username" value="user@email.com" />
         <cfhttpparam type="formField" name="password" value="userspassword" />

        </cfhttp>       
        <cfset rc.result = cfhttp.fileContent />     
我确保我的ip范围被列为白名单,我的ip松弛设置为松弛,Alluser可以自我授权,我尝试了不同的用户名和密码参数,我得到的只是关于无效授权的相同错误


非常感谢您的帮助

我无法发表评论,因此我必须回答:)但这实际上只是一个建议。当您使用
时,默认情况下ColdFusion URL会为您进行编码。ColdFusion将编码字符
~
-
,但根据RFC 3986规范(请参阅),它实际上不应该这样做,因为它们是无保留字符。如果您的表单字段包含这些字符(我怀疑它们包含,因为您的示例显示了电子邮件地址),则可能是这些字符编码不正确导致了身份验证失败

作为快速测试,您可以将
encoded=“false”
添加到
标记中,然后自己使用
encodeForUrl()
urlEncodedFormat()
(取决于您的ColdFusion版本)对其值进行url编码,然后撤消错误的编码:

 <cfhttpparam type="formField" encoded="false" name="username" value="#replacelist(urlEncodedFormat('user@email.com'), '%2D,%2E,%5F,%7E', '-,.,_,~')#">

下面是从我为访问salesforce而创建的CFC中提取的一些CFScript代码。(不会按原样运行,但逻辑是存在的-抱歉,代码太多,无法复制完整内容)。希望这会有所帮助

我主要使用与您相同的方法,但您可能想要窃取一些特定设置(字符集、内容类型、接受)

我伪造了loginCredentials结构中的值,但它们的格式大致相同(与您自己的格式相比)

这对我们在Railo上运行很好。也许还需要检查这不是SSL问题-您是否需要将SSL证书添加到Coldfusion中,以便它可以与Salesforce对话

variables.sfAuthDomain = "https://login.salesforce.com";

variables.authServiceURL = variables.sfAuthDomain & "/services/oauth2/token";

variables.accessToken = "xxxxx"    // The access token returned by SF, used on future logins

variables.loginCredentials = {
    "grant_type": "password",
    "client_id": "3MVG9Fkjshdkfjvshd ckjfhjkch.blkjlkjlkjkljl.wkjhgkjhkjhds.mVk84TRzhm_pXxK6_786786",
    "client_secret": "3887687686868668727",
    "username": "huge.duck@monkey.com.icom.icomqa",
    "password": "Bungerloo!PPkjhj324ij45bQGyymmd"
};


/**
 * MAKE SERVICE CALL
 * Makes HTTP service call
 **/
public Struct function makeServiceCall(String serviceUrl, String method="GET", Boolean sfAuth=true, Struct headers={}, Struct formFields) {

    var httpService = new http();    // create new http service

    var httpResponse = {};

    var fieldName = "";

    var bodyData = "";

    /* set attributes using implicit setters */
    httpService.setMethod(arguments.method);
    httpService.setCharset("utf-8");
    httpService.setUrl(Trim(arguments.serviceURL));
    httpService.setTimeOut(variables.timeoutValue);

    /* add httpparams using addParam() */        
    for(fieldName in arguments.headers) {
        httpService.addParam(type="header", name="#fieldName#", value="#arguments.headers[fieldName]#");            
    }

    if(arguments.sfAuth){
        httpService.addParam(type="header", name="Authorization", value="OAuth #variables.accessToken#");
    }

    if(StructKeyExists(arguments, "formFields")) {
        loop collection="#arguments.formFields#" item="fieldName" {
            bodyData = ListAppend(bodyData, "#fieldName#=#formFields[fieldName]#", "&");
        }
    }

    if(bodyData is not "") {
        httpService.addParam(type="body", name="post", encoded="no", value="#bodyData#");
    }

    /* make the http call to the URL using send() */
    httpResponse = httpService.send().getPrefix();

    //dump(httpResponse, false, "modern", "", 500, "httpResponse");

    return httpResponse;

}

httpResponse = makeServiceCall(
    serviceUrl = serviceURL,
    method = "POST", 
    sfAuth = false,
    headers = {
        "Content-Type": "application/x-www-form-urlencoded",
        "accept": "text/json"
    },
    formFields = loginCredentials    
);

最终将我的coldfusion服务器更改为使用TLS 1.2,因为salesforce不推荐使用TLS 1.0。希望我的答案和本文中给出的有用答案能帮助其他人

您的密码表单字段值为“仅包含密码”,因此会显示此类错误:

({“error”:“invalid\u grant”,“error\u description”:“authentication failure”})

必须包含(密码和安全令牌)


cUrl代码是执行post还是get的代码?@DanBracuk我认为它必须是post,我认为您不能作为get请求令牌
variables.sfAuthDomain = "https://login.salesforce.com";

variables.authServiceURL = variables.sfAuthDomain & "/services/oauth2/token";

variables.accessToken = "xxxxx"    // The access token returned by SF, used on future logins

variables.loginCredentials = {
    "grant_type": "password",
    "client_id": "3MVG9Fkjshdkfjvshd ckjfhjkch.blkjlkjlkjkljl.wkjhgkjhkjhds.mVk84TRzhm_pXxK6_786786",
    "client_secret": "3887687686868668727",
    "username": "huge.duck@monkey.com.icom.icomqa",
    "password": "Bungerloo!PPkjhj324ij45bQGyymmd"
};


/**
 * MAKE SERVICE CALL
 * Makes HTTP service call
 **/
public Struct function makeServiceCall(String serviceUrl, String method="GET", Boolean sfAuth=true, Struct headers={}, Struct formFields) {

    var httpService = new http();    // create new http service

    var httpResponse = {};

    var fieldName = "";

    var bodyData = "";

    /* set attributes using implicit setters */
    httpService.setMethod(arguments.method);
    httpService.setCharset("utf-8");
    httpService.setUrl(Trim(arguments.serviceURL));
    httpService.setTimeOut(variables.timeoutValue);

    /* add httpparams using addParam() */        
    for(fieldName in arguments.headers) {
        httpService.addParam(type="header", name="#fieldName#", value="#arguments.headers[fieldName]#");            
    }

    if(arguments.sfAuth){
        httpService.addParam(type="header", name="Authorization", value="OAuth #variables.accessToken#");
    }

    if(StructKeyExists(arguments, "formFields")) {
        loop collection="#arguments.formFields#" item="fieldName" {
            bodyData = ListAppend(bodyData, "#fieldName#=#formFields[fieldName]#", "&");
        }
    }

    if(bodyData is not "") {
        httpService.addParam(type="body", name="post", encoded="no", value="#bodyData#");
    }

    /* make the http call to the URL using send() */
    httpResponse = httpService.send().getPrefix();

    //dump(httpResponse, false, "modern", "", 500, "httpResponse");

    return httpResponse;

}

httpResponse = makeServiceCall(
    serviceUrl = serviceURL,
    method = "POST", 
    sfAuth = false,
    headers = {
        "Content-Type": "application/x-www-form-urlencoded",
        "accept": "text/json"
    },
    formFields = loginCredentials    
);