通过 HTTPS 使用 CRM 365 本地 Web Api
Consuming CRM 365 on-premise Web Api via HTTPS
我有以下代码可以按预期工作:
var credentials = new NetworkCredential(UserName, Password, Domain);
var httpMessageHandler = new HttpClientHandler { Credentials = credentials };
HttpClient httpClient = new HttpClient(httpMessageHandler);
try
{
using (httpClient)
{
httpClient.BaseAddress = new Uri(ResourceUrl);
httpClient.Timeout = new TimeSpan(0, 2, 0); //2 minutes
var response = httpClient.GetAsync("data/v8.2/contacts?$top=1", HttpCompletionOption.ResponseHeadersRead).Result;
var response1Content = response.Content.ReadAsStringAsync().Result;
}
}
但是,当我尝试通过 HTTPS(其中 ADFS 3 是权限)访问同一资源时,我无法访问。
Microsoft 提供了一些封装在 Authorization
class here 中的示例帮助程序代码。我用过这个,所以我的代码现在看起来像这样:
Configuration configuration = new Configuration();
configuration.Username = UserName;
configuration.Password = secure;
configuration.Domain = Domain;
configuration.ServiceUrl = ServiceUrl;
configuration.RedirectUrl = RedirectUrl;
configuration.ClientId = ClientId;
var credentials = new NetworkCredential(UserName, Password, Domain);
var httpMessageHandler = new HttpClientHandler { Credentials = credentials };
Authentication authentication = new Authentication(configuration, AdfsUrl);
OAuthMessageHandler oAuthHttpMessageHandler = new OAuthMessageHandler(authentication, httpMessageHandler);
HttpClient httpClient = new HttpClient(oAuthHttpMessageHandler);
try
{
using (httpClient)
{
httpClient.BaseAddress = new Uri(ServiceUrl);
httpClient.Timeout = new TimeSpan(0, 2, 0); //2 minutes
var response = httpClient.GetAsync("data/v8.2/contacts?$top=1", HttpCompletionOption.ResponseHeadersRead).Result;
var response1Content = response.Content.ReadAsStringAsync().Result;
}
}
然而,当它到达这一行时,这给了我以下异常:
var response = httpClient.GetAsync("data/v8.2/contacts?$top=1", HttpCompletionOption.ResponseHeadersRead).Result;
如有任何建议,我们将不胜感激。
最后我不得不实施一个 multi-step 自定义解决方案:
第 1 步。 POST 到
https://myadfs.com/adfs/oauth2/authorize?response_type=code&redirect_uri=https://mywebsiterequiringadfsauthorisation.com&resource=https://mywebsiterequiringadfsauthorisation.com&client_id=12ab34cd-12ab-12ab-12ab-12ab3412abcd&RedirectToIdentityProvider=https://myadfs.com//adfs/services/trust
以及以下 body:
Body:
response_type:code
redirect_uri:https://mywebsiterequiringadfsauthorisation.com
resource:https://mywebsiterequiringadfsauthorisation.com
client_id:12ab34cd-12ab-12ab-12ab-12ab3412abcd
RedirectToIdentityProvider:https://myadfs.com/adfs/services/trust
这一步如果成功 returns 来自服务器的 301 Found 响应。响应的 Headers 包含 Location,看起来像这样:
Location:
https://mywebsiterequiringadfsauthorisation.com:443/?code=HotI0lPfMEGhcEo7zXqFEQ.yjKLgch71ggSADojHBJkCobAXTU.gomySyiXeFHuXohPstY5MOtH_eRp4Cnr65q3PaIEXZ-Fz3dp-e25hr09QDUDBCqz08ROWEN9tcoZEAwAKG_pepLTnNVHOZwbrhaYlc2XRjZ4IrCJGZPqfapnQphXDR_4cPl7tIIt3q7ORaVF5LbAyv76bTeCGqKSNsCmeP6IrGigZoDBBxAdfGMg-Pg_Ebs_SaPY1P3Q2egKkkpCYfks8-kkHJNAhS5Wv2Qio_XzIdUOO6zWU9YGdGQdC1U-VNeHwJDm8GzVtXxbD9aTdQFwdUlg2DELyQxEOPcDLQG2BKmdxRGF3jRd_OUvaIzsKVz4u0fcNpeIhXNHsYGtvRZHLw
第 2 步
从响应的 Header/Location 中提取代码并构造对 ADFS 的第二个请求:
POST 至 https://myadfs.com/adfs/oauth2/token
具有以下 body 内容:
Body:
client_id:12ab34cd-12ab-12ab-12ab-12ab3412abcd
redirect_uri:https://mywebsiterequiringadfsauthorisation.com
grant_type:authorization_code
code:HotI0lPfMEGhcEo7zXqFEQ.yjKLgch71ggSADojHBJkCobAXTU.gomySyiXeFHuXohPstY5MOtH_eRp4Cnr65q3PaIEXZ-Fz3dp-e25hr09QDUDBCqz08ROWEN9tcoZEAwAKG_pepLTnNVHOZwbrhaYlc2XRjZ4IrCJGZPqfapnQphXDR_4cPl7tIIt3q7ORaVF5LbAyv76bTeCGqKSNsCmeP6IrGigZoDBBxAdfGMg-Pg_Ebs_SaPY1P3Q2egKkkpCYfks8-kkHJNAhS5Wv2Qio_XzIdUOO6zWU9YGdGQdC1U-VNeHwJDm8GzVtXxbD9aTdQFwdUlg2DELyQxEOPcDLQG2BKmdxRGF3jRd_OUvaIzsKVz4u0fcNpeIhXNHsYGtvRZHLw
如果一切正常,您应该会收到 200 OK 响应,其中 JSON 响应包含您的访问令牌:
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IlhscG9zR0pGbjE3OHlrNWFwcjl0R01ERGdwNCJ9.eyJhdWQiOiJodHRwczovL2N3Y3JtLnRoZWZhLmNvbS8iLCJpc3MiOiJodHRwczovL3dnc3N0c3IudGhlZmEuY29tL2FkZnMvc2VydmljZXMvdHJ1c3QiLCJpYXQiOjE1NDcxMTc3ODAsImV4cCI6MTU0NzIwNDE4MCwidXBuIjoicHJkX2N3MjAxNl9pbnRAdGhlZmEubG9jYWwiLCJwcmltYXJ5c2lkIjoiUy0xLTUtMjEtMTc1OTM5NjE5My0yMDMwMjE4Mzg4LTM0NjczNTc3OTMtMzc5NiIsInVuaXF1ZV9uYW1lIjoiVEhFRkFcXFBSRF9DVzIwMTZfSU5UIiwiYXV0aF90aW1lIjoiMjAxOS0wMS0xMFQxMDo1NjoxNC42NDVaIiwiYXV0aG1ldGhvZCI6InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphYzpjbGFzc2VzOlBhc3N3b3JkUHJvdGVjdGVkVHJhbnNwb3J0IiwidmVyIjoiMS4wIiwiYXBwaWQiOiIxMmFiMzRjZC0xMmFiLTEyYWItMTJhYi0xMmFiMzQxMmFiY2QifQ.fdvBavODiXOQM-UNBD59sgvqz357P5DzEOGifY0TfMZUjGrHc-IdZU9eqJNsUbtK4_FsrnoV6OKK8Vc4tvDITIw5D8i5uPP0tK_yDWs3Jdw5v3RUDDH2Q5yWrEed6KASO40q-YeowzMaLkf3EDE33Iyrh_J5K29hYnVJJ_4uVxAxdzIAM-Mp9HqfLtpwtEOyWe3PaTjGe8uGRXKstOFy0yNFvURaEohp628EYmA_lieTXA0TVVXG-KCV5QfuG7SWblErPR7nZI27iSs4xPyWkf68JfQOodfQ5iDHR3AWcWtNPd2b2h7VdKO3gMUsux9e__GO43Uzu9hf_l3nOMvNbA",
"token_type": "bearer",
"expires_in": 86400
}
第 3 步
将访问令牌放入任何后续请求的 Header 中。
我有以下代码可以按预期工作:
var credentials = new NetworkCredential(UserName, Password, Domain);
var httpMessageHandler = new HttpClientHandler { Credentials = credentials };
HttpClient httpClient = new HttpClient(httpMessageHandler);
try
{
using (httpClient)
{
httpClient.BaseAddress = new Uri(ResourceUrl);
httpClient.Timeout = new TimeSpan(0, 2, 0); //2 minutes
var response = httpClient.GetAsync("data/v8.2/contacts?$top=1", HttpCompletionOption.ResponseHeadersRead).Result;
var response1Content = response.Content.ReadAsStringAsync().Result;
}
}
但是,当我尝试通过 HTTPS(其中 ADFS 3 是权限)访问同一资源时,我无法访问。
Microsoft 提供了一些封装在 Authorization
class here 中的示例帮助程序代码。我用过这个,所以我的代码现在看起来像这样:
Configuration configuration = new Configuration();
configuration.Username = UserName;
configuration.Password = secure;
configuration.Domain = Domain;
configuration.ServiceUrl = ServiceUrl;
configuration.RedirectUrl = RedirectUrl;
configuration.ClientId = ClientId;
var credentials = new NetworkCredential(UserName, Password, Domain);
var httpMessageHandler = new HttpClientHandler { Credentials = credentials };
Authentication authentication = new Authentication(configuration, AdfsUrl);
OAuthMessageHandler oAuthHttpMessageHandler = new OAuthMessageHandler(authentication, httpMessageHandler);
HttpClient httpClient = new HttpClient(oAuthHttpMessageHandler);
try
{
using (httpClient)
{
httpClient.BaseAddress = new Uri(ServiceUrl);
httpClient.Timeout = new TimeSpan(0, 2, 0); //2 minutes
var response = httpClient.GetAsync("data/v8.2/contacts?$top=1", HttpCompletionOption.ResponseHeadersRead).Result;
var response1Content = response.Content.ReadAsStringAsync().Result;
}
}
然而,当它到达这一行时,这给了我以下异常:
var response = httpClient.GetAsync("data/v8.2/contacts?$top=1", HttpCompletionOption.ResponseHeadersRead).Result;
如有任何建议,我们将不胜感激。
最后我不得不实施一个 multi-step 自定义解决方案:
第 1 步。 POST 到
https://myadfs.com/adfs/oauth2/authorize?response_type=code&redirect_uri=https://mywebsiterequiringadfsauthorisation.com&resource=https://mywebsiterequiringadfsauthorisation.com&client_id=12ab34cd-12ab-12ab-12ab-12ab3412abcd&RedirectToIdentityProvider=https://myadfs.com//adfs/services/trust
以及以下 body:
Body:
response_type:code
redirect_uri:https://mywebsiterequiringadfsauthorisation.com
resource:https://mywebsiterequiringadfsauthorisation.com
client_id:12ab34cd-12ab-12ab-12ab-12ab3412abcd
RedirectToIdentityProvider:https://myadfs.com/adfs/services/trust
这一步如果成功 returns 来自服务器的 301 Found 响应。响应的 Headers 包含 Location,看起来像这样:
Location:
https://mywebsiterequiringadfsauthorisation.com:443/?code=HotI0lPfMEGhcEo7zXqFEQ.yjKLgch71ggSADojHBJkCobAXTU.gomySyiXeFHuXohPstY5MOtH_eRp4Cnr65q3PaIEXZ-Fz3dp-e25hr09QDUDBCqz08ROWEN9tcoZEAwAKG_pepLTnNVHOZwbrhaYlc2XRjZ4IrCJGZPqfapnQphXDR_4cPl7tIIt3q7ORaVF5LbAyv76bTeCGqKSNsCmeP6IrGigZoDBBxAdfGMg-Pg_Ebs_SaPY1P3Q2egKkkpCYfks8-kkHJNAhS5Wv2Qio_XzIdUOO6zWU9YGdGQdC1U-VNeHwJDm8GzVtXxbD9aTdQFwdUlg2DELyQxEOPcDLQG2BKmdxRGF3jRd_OUvaIzsKVz4u0fcNpeIhXNHsYGtvRZHLw
第 2 步 从响应的 Header/Location 中提取代码并构造对 ADFS 的第二个请求:
POST 至 https://myadfs.com/adfs/oauth2/token
具有以下 body 内容:
Body:
client_id:12ab34cd-12ab-12ab-12ab-12ab3412abcd
redirect_uri:https://mywebsiterequiringadfsauthorisation.com
grant_type:authorization_code
code:HotI0lPfMEGhcEo7zXqFEQ.yjKLgch71ggSADojHBJkCobAXTU.gomySyiXeFHuXohPstY5MOtH_eRp4Cnr65q3PaIEXZ-Fz3dp-e25hr09QDUDBCqz08ROWEN9tcoZEAwAKG_pepLTnNVHOZwbrhaYlc2XRjZ4IrCJGZPqfapnQphXDR_4cPl7tIIt3q7ORaVF5LbAyv76bTeCGqKSNsCmeP6IrGigZoDBBxAdfGMg-Pg_Ebs_SaPY1P3Q2egKkkpCYfks8-kkHJNAhS5Wv2Qio_XzIdUOO6zWU9YGdGQdC1U-VNeHwJDm8GzVtXxbD9aTdQFwdUlg2DELyQxEOPcDLQG2BKmdxRGF3jRd_OUvaIzsKVz4u0fcNpeIhXNHsYGtvRZHLw
如果一切正常,您应该会收到 200 OK 响应,其中 JSON 响应包含您的访问令牌:
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IlhscG9zR0pGbjE3OHlrNWFwcjl0R01ERGdwNCJ9.eyJhdWQiOiJodHRwczovL2N3Y3JtLnRoZWZhLmNvbS8iLCJpc3MiOiJodHRwczovL3dnc3N0c3IudGhlZmEuY29tL2FkZnMvc2VydmljZXMvdHJ1c3QiLCJpYXQiOjE1NDcxMTc3ODAsImV4cCI6MTU0NzIwNDE4MCwidXBuIjoicHJkX2N3MjAxNl9pbnRAdGhlZmEubG9jYWwiLCJwcmltYXJ5c2lkIjoiUy0xLTUtMjEtMTc1OTM5NjE5My0yMDMwMjE4Mzg4LTM0NjczNTc3OTMtMzc5NiIsInVuaXF1ZV9uYW1lIjoiVEhFRkFcXFBSRF9DVzIwMTZfSU5UIiwiYXV0aF90aW1lIjoiMjAxOS0wMS0xMFQxMDo1NjoxNC42NDVaIiwiYXV0aG1ldGhvZCI6InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphYzpjbGFzc2VzOlBhc3N3b3JkUHJvdGVjdGVkVHJhbnNwb3J0IiwidmVyIjoiMS4wIiwiYXBwaWQiOiIxMmFiMzRjZC0xMmFiLTEyYWItMTJhYi0xMmFiMzQxMmFiY2QifQ.fdvBavODiXOQM-UNBD59sgvqz357P5DzEOGifY0TfMZUjGrHc-IdZU9eqJNsUbtK4_FsrnoV6OKK8Vc4tvDITIw5D8i5uPP0tK_yDWs3Jdw5v3RUDDH2Q5yWrEed6KASO40q-YeowzMaLkf3EDE33Iyrh_J5K29hYnVJJ_4uVxAxdzIAM-Mp9HqfLtpwtEOyWe3PaTjGe8uGRXKstOFy0yNFvURaEohp628EYmA_lieTXA0TVVXG-KCV5QfuG7SWblErPR7nZI27iSs4xPyWkf68JfQOodfQ5iDHR3AWcWtNPd2b2h7VdKO3gMUsux9e__GO43Uzu9hf_l3nOMvNbA",
"token_type": "bearer",
"expires_in": 86400
}
第 3 步
将访问令牌放入任何后续请求的 Header 中。