2017-07-04 100 views
3

我正在尝试使用基于令牌的验证来对Netsuite API进行SOAP调用。我有一个从WDSL生成的C#客户端,它正在发送以下请求(秘密被替换)。基于Netsuite令牌的API调用中的模糊验证

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:messages_2016_2.platform.webservices.netsuite.com" xmlns:urn1="urn:core_2016_2.platform.webservices.netsuite.com"> 
    <soapenv:Header> 
     <urn:partnerInfo> 
     <urn:partnerId>[MyAccountId]</urn:partnerId> 
     </urn:partnerInfo> 
     <urn:applicationInfo> 
     <urn:applicationId>[MyApplicationId]</urn:applicationId> 
     </urn:applicationInfo> 
     <urn:tokenPassport> 
     <urn1:account>[MyAccountId]</urn1:account> 
     <urn1:consumerKey>[MyConsumerKey]</urn1:consumerKey> 
     <urn1:token>[MyTokenId]</urn1:token> 
     <urn1:nonce>1574515852</urn1:nonce> 
     <urn1:timestamp>1499135589</urn1:timestamp> 
     <urn1:signature algorithm="HMAC-SHA1">Ll8DbLvTWsBh/G7UtenErR03OrM=</urn1:signature> 
     </urn:tokenPassport> 
    </soapenv:Header> 
    <soapenv:Body> 
     <urn:getDataCenterUrls> 
     <urn:account>[MyAccountId]</urn:account> 
     </urn:getDataCenterUrls> 
    </soapenv:Body> 
</soapenv:Envelope> 

我得到如下回应

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <soapenv:Body> 
     <soapenv:Fault> 
     <faultcode>soapenv:Server.userException</faultcode> 
     <faultstring>Ambiguous authentication</faultstring> 
     <detail> 
      <platformFaults:invalidCredentialsFault xmlns:platformFaults="urn:faults_2016_2.platform.webservices.netsuite.com"> 
       <platformFaults:code>USER_ERROR</platformFaults:code> 
       <platformFaults:message>Ambiguous authentication</platformFaults:message> 
      </platformFaults:invalidCredentialsFault> 
      <ns1:hostname xmlns:ns1="http://xml.apache.org/axis/">partners-java20004.sea.netledger.com</ns1:hostname> 
     </detail> 
     </soapenv:Fault> 
    </soapenv:Body> 
</soapenv:Envelope> 

我已经试过很多生成签名,和时间戳的方式不同。目前我有以下几种:

private string computeNonce() 
{ 
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 
    byte[] data = new byte[20]; 
    rng.GetBytes(data); 
    int value = Math.Abs(BitConverter.ToInt32(data, 0)); 
    return value.ToString(); 
} 

private long computeTimestamp() 
{ 
    return ((long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds); 
} 

private TokenPassportSignature computeSignature(string accountId, string consumerKey, string consumerSecret, string tokenId, string tokenSecret, string nonce, long timestamp) 
{ 
    string baseString = accountId + "&" + consumerKey + "&" + tokenId + "&" + nonce + "&" + timestamp; 
    string key = consumerSecret + "&" + tokenSecret; 
    string signature = ""; 
    var encoding = new System.Text.ASCIIEncoding(); 
    byte[] keyBytes = encoding.GetBytes(key); 
    byte[] baseStringBytes = encoding.GetBytes(baseString); 
    using (var hmacSha1 = new HMACSHA1(keyBytes)) 
    { 
     byte[] hashBaseString = hmacSha1.ComputeHash(baseStringBytes); 
     signature = Convert.ToBase64String(hashBaseString); 
    } 
    TokenPassportSignature sign = new TokenPassportSignature(); 
    sign.algorithm = "HMAC-SHA1"; 
    sign.Value = signature; 
    return sign; 
} 

有没有人有任何想法?谢谢!

回答

0

我不知道它是如何在C#中使用HMAC-SHA1,但在Javascript实现与CryptoJS HMAC-SHA256你第一次签署的字符串,然后对其进行编码为Base64:

var baseString = ACCOUNT_ID + "&" + NETSUITE_CONSUMER_KEY + "&" + NETSUITE_TOKEN_ID + "&" + NONCE + "&" + TIMESTAMP; 
var key = NETSUITE_CONSUMER_SECRET + '&' + NETSUITE_TOKEN_SECRET; 
var HMAC256_Sig = cryptoJS.HmacSHA256(baseString, key); 
var HMAC256_Sig_Base64 = cryptoJS.enc.Base64.stringify(HMAC256_Sig); 

然后你输出它像:

'<platformCore:signature algorithm = "HMAC_SHA256">' + HMAC256_Sig_Base64 + '</platformCore:signature>' 
+0

谢谢您的回答。你是说我生成签名的方式是错误的。你怎么能确定。错误只是说“模糊认证”。 – ChrisBellew

+0

我不能确定,但​​它值得一试,因为没有其他东西从你的代码中跳出来。 –

+0

我已经经历了一段时间,但是我记得得到了“不明确的身份验证”错误,我试过的最后一件事是摆脱了它,最后是在做Base64。 –

4

getDataCenter调用不需要护照。我只是与mapSso函数有同样的问题。它看起来像2017.1版本使他们在不接受护照时更严格

+0

就是这样!谢谢!我正在使用此调用进行测试,因此我从此调用中删除了此令牌护照,并将其留在所有其他调用中,并开始工作。 – ChrisBellew

+0

通过删除tokenPassport,我能够单独成功运行getDataCenter请求。但是,如果我尝试了一个失败的vendorBill调用。你能帮忙吗? – Chinni

+0

你必须拥有供应商账单的护照。这是您必须通过身份验证的敏感信息。数据中心是“免费”信息。 – bknights

0

取出护照。可悲的是,如果您在使用令牌身份验证时在代码中包含此代码,则NetSuite会失败。 :/

0

我不得不修改XML并删除tokenpassport(帐户,comsumer密钥,令牌,随机数,时间戳)标签,它的工作。

0

我知道这是一个老问题,但我努力解决同样的问题,并找到了一个可行的解决方案。

private static void CreateTokenPassport() 
{ 
    // Initialize the netsuite web service proxy. 
    _netSuiteService = new NetSuiteService(); 

    // A valid Token passport signature consists of the following: 
    // Create a base string. 
    //  The base string is variable created from concatenating a series of values specific to the request.Use an ampersand as a delimiter between values. 
    //  The values should be arranged in the following sequence: 
    // NetSuite account ID 
    // Consumer key 
    // Token 
    // Nonce(a unique, randomly generated alphanumeric string, with a minimum of six characters and maximum of 64) 
    // Timestamp 
    // See: https://system.na1.netsuite.com/app/help/helpcenter.nl?fid=section_4395630653.html#bridgehead_4398049137 

    string consumerSecret = ""; 
    string tokenSecret = ""; 
    string accountId = ""; 
    string consumerKey = ""; 
    string tokenId = ""; 
    string nonce = ComputeNonce(); 
    long timestamp = ComputeTimestamp(); 

    string baseString = string.Format("{0}&{1}&{2}&{3}&{4}", accountId, consumerKey, tokenId, nonce, timestamp); 
    string secretKey = string.Format("{0}&{1}", consumerSecret, tokenSecret); 

    // Initialize the keyed hash object using the secret key as the key 
    HMACSHA256 hashObject = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey)); 

    // Computes the signature by hashing the data with the secret key as the key 
    byte[] signature = hashObject.ComputeHash(Encoding.UTF8.GetBytes(baseString)); 

    // Base 64 Encode 
    string encodedSignature = Convert.ToBase64String(signature); 

    TokenPassport tokenPassport = new TokenPassport 
    { 
     signature = new TokenPassportSignature 
     { 
      Value = encodedSignature, 
      algorithm = "HMAC_SHA256" 
     }, 
     account = accountId, 
     consumerKey = consumerKey, 
     token = tokenId, 
     nonce = nonce, 
     timestamp = timestamp 
    }; 

    _netSuiteService = new NetSuiteService 
    { 
     tokenPassport = tokenPassport 
    }; 
} 

实用方法:

private static string ComputeNonce() 
{ 
    return Guid.NewGuid().ToString("N"); 
} 

private static long ComputeTimestamp() 
{ 
    return ((long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds); 
} 
相关问题