来自 C# 客户端的 SalesForce 身份验证错误
Error with SalesForce authentication from C# Client(s)
我是 SalesForce 的新手,正在努力快速掌握基础知识,因为我们将在下周开始一个大型集成项目。对于我们集成的至少一部分,我们将需要访问 SalesForce Rest API。为此,我和我团队中的另一位绅士使用 Postman 完成了一些基本的呼叫原型设计,并取得了巨大成功,尤其是在 OAuth2 身份验证方面。我们的问题是,虽然在 Postman 中一切似乎都运行良好,但一旦我们切换到使用 C# 进行调用,我们就会开始收到错误信息,而不是我们的身份验证令牌。响应为 HTTP Status 400 Bad Request,响应内容为
{"error":"invalid_grant","error_description":"authentication failure"}.
这是我们尝试过的一些 C# 代码的示例:
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Web;
namespace SFTokenTest
{
internal class Program
{
private const string LoginUrl = "https://test.salesforce.com/services/oauth2/token";
private static void Main(string[] args)
{
FormUrlEncodedContent content = new FormUrlEncodedContent(new []
{
new KeyValuePair<string, string>("grant_type",HttpUtility.UrlEncode("password")),
new KeyValuePair<string, string>("password",HttpUtility.UrlEncode("PASSWORD")),
new KeyValuePair<string, string>("username", HttpUtility.UrlEncode("USERNAME")),
new KeyValuePair<string, string>("client_id",HttpUtility.UrlEncode("CLIENTID")),
new KeyValuePair<string, string>("client_secret",HttpUtility.UrlEncode("CLIENTSECRET"))
});
HttpResponseMessage response;
using (HttpClient client = new HttpClient())
{
response = client.PostAsync(LoginUrl, content).Result;
}
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
Console.WriteLine(response.StatusCode);
Console.ReadLine();
}
}
}
注意:这是我们尝试过的许多实现之一,包括使用 HttpWebRequest 和 WebClient,所有实现都具有相同的结果。
除了我们自己的代码之外,我们还尝试从 GitHub 存储库 developerforce/Force 中提取代码。com-Toolkit-for-NET 也出现了同样的问题。
到目前为止,我们花了两天时间解决这个问题,但没有成功,而且我们已经让我们的 SalesForce 顾问不明白为什么它不起作用。我们今天下午尝试重置安全令牌也无济于事。我浏览了很多在线文章(包括 Whosebug 上的文章),其中大部分都指向以下问题:
- 错误的凭据 - 我们在 Postman 中成功使用了我们试图在 C# 应用程序中使用的相同凭据,我们已经尝试 re-coping 并从 SalesForce UI 粘贴它们我们已经尝试将它们手动键入我们的代码,以防我们拾取不可见的字符。 (根据凭据,我包括用户名、密码、client_id 和客户端密码。)
- 错误或丢失 Content-Type header - 我们肯定会发送 "application/x-www-form-urlencoded" 我已经在每个应用程序中检查了很多次(并且已经嗅探以验证它确实被发送了).
- 未编码的参数 - 我在许多 Whosebug 线程上看到了这一点,并验证了我们正在对发送给请求的参数进行编码 body。
似乎 Postman 正在做一些我们不在我们的请求中的事情,但我似乎无法确定它是什么。我们甚至捕获了 Postman 和我们的一位客户的请求,并对它们进行了区分,结果返回时它们是相同的。
如有任何帮助,我们将不胜感激。
如果您还没有解决这个问题,我认为这可能是您的问题。
所以根据这个:https://help.salesforce.com/apex/HTViewSolution?id=000221207
从 2016 年 6 月开始,Salesforce 将分阶段在整个平台上禁用 TLS 1.0 加密。
如果您使用的是 .net 4.6 之前的任何版本,则意味着您不会默认打开 TLS 1.1/1,2。这里有一些选项列表,您可以使用它来启用它:https://help.salesforce.com/apex/HTViewSolution?id=000221207#Inboundintegrations
对于像您这样的控制台应用程序,刚刚在我这边进行了测试,以下内容对我有用(在 .net 4.5.2 上):
string LoginUrl = "https://login.salesforce.com/services/oauth2/token";
//the line below enables TLS1.1 and TLS1.2
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
FormUrlEncodedContent content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("client_id","CLIENTID"),
new KeyValuePair<string, string>("client_secret","CLIENTSECRET"),
new KeyValuePair<string, string>("password","PASSWORD + SECURITYTOKEN"),
new KeyValuePair<string, string>("username", "USERNAME")
});
HttpResponseMessage response;
using (HttpClient client = new HttpClient())
{
response = client.PostAsync(LoginUrl, content).Result;
}
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
Console.WriteLine(response.StatusCode);
Console.ReadLine();
我是 SalesForce 的新手,正在努力快速掌握基础知识,因为我们将在下周开始一个大型集成项目。对于我们集成的至少一部分,我们将需要访问 SalesForce Rest API。为此,我和我团队中的另一位绅士使用 Postman 完成了一些基本的呼叫原型设计,并取得了巨大成功,尤其是在 OAuth2 身份验证方面。我们的问题是,虽然在 Postman 中一切似乎都运行良好,但一旦我们切换到使用 C# 进行调用,我们就会开始收到错误信息,而不是我们的身份验证令牌。响应为 HTTP Status 400 Bad Request,响应内容为
{"error":"invalid_grant","error_description":"authentication failure"}.
这是我们尝试过的一些 C# 代码的示例:
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Web;
namespace SFTokenTest
{
internal class Program
{
private const string LoginUrl = "https://test.salesforce.com/services/oauth2/token";
private static void Main(string[] args)
{
FormUrlEncodedContent content = new FormUrlEncodedContent(new []
{
new KeyValuePair<string, string>("grant_type",HttpUtility.UrlEncode("password")),
new KeyValuePair<string, string>("password",HttpUtility.UrlEncode("PASSWORD")),
new KeyValuePair<string, string>("username", HttpUtility.UrlEncode("USERNAME")),
new KeyValuePair<string, string>("client_id",HttpUtility.UrlEncode("CLIENTID")),
new KeyValuePair<string, string>("client_secret",HttpUtility.UrlEncode("CLIENTSECRET"))
});
HttpResponseMessage response;
using (HttpClient client = new HttpClient())
{
response = client.PostAsync(LoginUrl, content).Result;
}
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
Console.WriteLine(response.StatusCode);
Console.ReadLine();
}
}
}
注意:这是我们尝试过的许多实现之一,包括使用 HttpWebRequest 和 WebClient,所有实现都具有相同的结果。
除了我们自己的代码之外,我们还尝试从 GitHub 存储库 developerforce/Force 中提取代码。com-Toolkit-for-NET 也出现了同样的问题。
到目前为止,我们花了两天时间解决这个问题,但没有成功,而且我们已经让我们的 SalesForce 顾问不明白为什么它不起作用。我们今天下午尝试重置安全令牌也无济于事。我浏览了很多在线文章(包括 Whosebug 上的文章),其中大部分都指向以下问题:
- 错误的凭据 - 我们在 Postman 中成功使用了我们试图在 C# 应用程序中使用的相同凭据,我们已经尝试 re-coping 并从 SalesForce UI 粘贴它们我们已经尝试将它们手动键入我们的代码,以防我们拾取不可见的字符。 (根据凭据,我包括用户名、密码、client_id 和客户端密码。)
- 错误或丢失 Content-Type header - 我们肯定会发送 "application/x-www-form-urlencoded" 我已经在每个应用程序中检查了很多次(并且已经嗅探以验证它确实被发送了).
- 未编码的参数 - 我在许多 Whosebug 线程上看到了这一点,并验证了我们正在对发送给请求的参数进行编码 body。
似乎 Postman 正在做一些我们不在我们的请求中的事情,但我似乎无法确定它是什么。我们甚至捕获了 Postman 和我们的一位客户的请求,并对它们进行了区分,结果返回时它们是相同的。
如有任何帮助,我们将不胜感激。
如果您还没有解决这个问题,我认为这可能是您的问题。 所以根据这个:https://help.salesforce.com/apex/HTViewSolution?id=000221207 从 2016 年 6 月开始,Salesforce 将分阶段在整个平台上禁用 TLS 1.0 加密。
如果您使用的是 .net 4.6 之前的任何版本,则意味着您不会默认打开 TLS 1.1/1,2。这里有一些选项列表,您可以使用它来启用它:https://help.salesforce.com/apex/HTViewSolution?id=000221207#Inboundintegrations
对于像您这样的控制台应用程序,刚刚在我这边进行了测试,以下内容对我有用(在 .net 4.5.2 上):
string LoginUrl = "https://login.salesforce.com/services/oauth2/token";
//the line below enables TLS1.1 and TLS1.2
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
FormUrlEncodedContent content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("client_id","CLIENTID"),
new KeyValuePair<string, string>("client_secret","CLIENTSECRET"),
new KeyValuePair<string, string>("password","PASSWORD + SECURITYTOKEN"),
new KeyValuePair<string, string>("username", "USERNAME")
});
HttpResponseMessage response;
using (HttpClient client = new HttpClient())
{
response = client.PostAsync(LoginUrl, content).Result;
}
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
Console.WriteLine(response.StatusCode);
Console.ReadLine();