19

我們已經使用了成功的將OData的V8.1端點在2016年impersonate a user.如何通過冒充OData的用戶

請注意,打算申請流程爲:郵差 - >本地主機的microService - > CRM從郵差工作請求的

示例 - > CRM(直接,無需經過微服務去)

Accept:application/json 
Content-Type:application/json; charset=utf-8 
OData-MaxVersion:4.0 
OData-Version:4.0 
MSCRMCallerID:d994d6ff-5531-e711-9422-00155dc0d345 
Cache-Control:no-cache 

反對的OData端點:..../api/data/v8.1/leads

注意,通過postman直接針對的OData V8.1端點發出只有當這是成功的。

當試圖做同樣的事情時,有一個服務在本地運行(郵差 - > LocalHost服務 - >客戶關係管理),這失敗了,並且簡單地忽略??? MSCRMCallerID標頭。

在檢查傳遞給從郵差,請求本地主機微服務,如在VS 2017檢查由調試器頭:

{Method: POST, RequestUri: 'https://.../api/data/v8.1/leads', Version: 1.1, Content: System.Net.Http.StringContent, Headers: 
{ 
    OData-Version: 4.0 
    OData-MaxVersion: 4.0 
    MSCRMCallerID: D994D6FF-5531-E711-9422-00155DC0D345 
    Cache-Control: no-cache 
    Accept: application/json 
    Content-Type: application/json; charset=utf-8 
}} 

該記錄成功創建,但是在CreatedBy字段是服務用戶名不是MSCRMCallerID用戶名(d994d6ff-5531-e711-9422-00155dc0d345),並且CreatedOnBehalf字段爲空。

我們做錯了什麼?

我們如何從我們的服務中獲得此模擬工作?

編輯+更多信息

請注意,我相信,我已經包括了所有的相關信息,但如果我沒有,請讓我知道我應該就這一問題提供什麼其他輸入。

我試過了什麼?

  1. 改變頭的順序
  2. 玩過頭
  3. 保證的情況下,該GUID是正確的用戶爲模擬的
  4. 保證用戶有一個代表和系統管理員角色(儘管這是不相關的,因爲這在執行直接針對crm odata端點的請求時起作用,而不是我們服務公開的端點
  5. 已經嘗試針對https和http執行請求
  6. 提琴手跟蹤如下所示

請注意,這提琴手跟蹤是表示郵差痕量 - >微服務請求。 它不顯示從localhost微服務到CRM的通信。(我不知道爲什麼,也許是因爲它已被加密)

POST https://localhost:19081/.....Leads/API/leads HTTP/1.1 
Host: localhost:19081 
Connection: keep-alive 
Content-Length: 84 
Cache-Control: no-cache 
Origin: chrome-extension://aicmkgpgakddgnaphhhpliifpcfhicfo 
MSCRMCallerID: D994D6FF-5531-E711-9422-00155DC0D345 
X-Postman-Interceptor-Id: d79b1d2e-2155-f2ec-4ad7-e9b63e7fb90d 
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 
Content-Type: application/json; charset=UTF-8 
Accept: */* 
Accept-Encoding: gzip, deflate, br 
Accept-Language: en-US,en;q=0.8 
Cookie: ai_user=Ka2Xn|2017-05-25T17:30:57.941Z 

{ 
    "subject": "created by mscrmcaller user2: d994d6ff-5531-e711-9422-00155dc0d345" 
} 

@Ram已經建議我們使用組織服務進行身份驗證,這是一種選擇,考慮到我們是針對Web API執行?請求的令牌是否仍然有效。 (請注意,這可能是一個愚蠢的問題,原因是因爲我不瞭解身份驗證如何工作)。

下面是來自我們如何在每次調用目前認證代碼片段:

//check headers to see if we got a redirect to the new location 
      var shouldAuthenticate = redirectUri.AbsoluteUri.Contains("adfs/ls"); 

      if (!shouldAuthenticate) 
      { 
       return; 
      } 

      var adfsServerName = redirectUri.Authority; 
      var queryParams = HttpUtility.ParseQueryString(redirectUri.Query); 

      ServicePointManager.ServerCertificateValidationCallback += 
       (sender, cert, chain, sslPolicyErrors) => true; 

      WSTrustChannelFactory factory = null; 
      try 
      { 
       // use a UserName Trust Binding for username authentication 
       factory = new WSTrustChannelFactory(
        new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), 
        $"https://{adfsServerName}/adfs/services/trust/13/usernamemixed") 
       { 
        Credentials = 
        { 
         UserName = 
         { 
          UserName = $"{credential.Domain}\\{credential.UserName}", 
          Password = credential.Password 
         } 
        }, 
        TrustVersion = TrustVersion.WSTrust13 
       }; 

       var rst = new RequestSecurityToken 
       { 
        RequestType = RequestTypes.Issue, 
        AppliesTo = new EndpointReference(_client.BaseAddress.AbsoluteUri), 
        TokenType = "urn:oasis:names:tc:SAML:1.0:assertion", 
        KeyType = KeyTypes.Bearer 
       }; 

       var channel = factory.CreateChannel(); 
       channel.Issue(rst, out RequestSecurityTokenResponse rstr); 

       var fedSerializer = new WSFederationSerializer(); 
       var rstrContent = fedSerializer.GetResponseAsString(rstr, new WSTrustSerializationContext()); 

       // construct a authentication form 
       var crmauthenticaionPostDictionary = new Dictionary<string, string> 
       { 
        {"wa", queryParams["wa"]}, 
        {"wresult", rstrContent}, 
        {"wctx", queryParams["wctx"]} 
       }; 

       // post the authentication form to the website. 
       var crmAuthorizationPostResponse = _client.PostAsync(_client.BaseAddress.AbsoluteUri, new FormUrlEncodedContent(crmauthenticaionPostDictionary)).Result; 

       var crmAuthorizationPostResponseString = crmAuthorizationPostResponse.Content.ReadAsStringAsync().Result; 
       //we should be authenticated here 
       if (
        !(
         // we are correctly authorized if we got redirected to the correct address that we 
         // were trying to reach in the first place. 
         crmAuthorizationPostResponse.StatusCode == HttpStatusCode.Redirect 
         && crmAuthorizationPostResponse.Headers.Location == authenticationTestUri 
        ) 
       ) 
       { 
        throw new Exception("ADFS Authentication to CRM failed."); 
       } 
+0

您是否可以驗證fiddler或瀏覽器網絡選項卡中的標題? –

+0

@ArvinVinoth謝謝你的問題,我更新了問題 –

+0

你能解決這個問題嗎? –

回答

3

當你正在做郵遞員CRM的要求,其直接調用& CRM處理它以預期的方式。

但是在Postman-> Microservice-> CRM中,標頭在Microservice和CRM之間丟失。

在您的微服務中,您必須手動將標題處理爲CRM SDK調用。

HttpWebRequest myHttpWebRequest1= (HttpWebRequest)WebRequest.Create(uri); 
myHttpWebRequest1.Headers.Add("MSCRMCallerID", "D994D6FF-5531-E711-9422-00155DC0D345"); 

或者HTTP Header Forwarding(對不起,我無法找到一個爲天青/ C#)

enter image description here

更新:

我假設你是以下這MSDN samples做你的CRM的Web API調用在c#microservice中。我已經包含了我們的標題 - MSCRMCallerID。看看它是否可以幫助你。

public async Task BasicCreateAndUpdatesAsync() 
{ 
    Console.WriteLine("--Section 1 started--"); 
    string queryOptions; //select, expand and filter clauses 
         //First create a new contact instance, then add additional property values and update 
         // several properties. 
         //Local representation of CRM Contact instance 
    contact1.Add("firstname", "Peter"); 
    contact1.Add("lastname", "Cambel"); 

    HttpRequestMessage createRequest1 = 
     new HttpRequestMessage(HttpMethod.Post, getVersionedWebAPIPath() + "contacts"); 
    createRequest1.Content = new StringContent(contact1.ToString(), 
     Encoding.UTF8, "application/json"); 

createRequest1.Headers.Add("MSCRMCallerID", "D994D6FF-5531-E711-9422-00155DC0D345"); 

    HttpResponseMessage createResponse1 = 
     await httpClient.SendAsync(createRequest1); 

    if (createResponse1.StatusCode == HttpStatusCode.NoContent) //204 
    { 
    Console.WriteLine("Contact '{0} {1}' created.", 
     contact1.GetValue("firstname"), contact1.GetValue("lastname")); 
    contact1Uri = createResponse1.Headers. 
     GetValues("OData-EntityId").FirstOrDefault(); 
    entityUris.Add(contact1Uri); 
    Console.WriteLine("Contact URI: {0}", contact1Uri); 
    } 
    else 
    { 
    Console.WriteLine("Failed to create contact for reason: {0}", 
     createResponse1.ReasonPhrase); 
    throw new CrmHttpResponseException(createResponse1.Content); 
    } 
} 
+1

這是一個很好的假設,但我檢查了從服務發送到CRM的頭文件。在Microsoft向我們發送對CRM的請求之前,我已經設置了一個斷點,並且我查看了請求,並且它顯示了所需的Hatter確實在請求之內。我不能100%確定標題不會丟失,因爲我無法在Fiddler中執行跟蹤,因爲Fiddler阻止了本地主機。 –

+0

我的意思是Microservice不是微軟在第一個評論 –

+0

偉大的,你調試它已經確定。 –

0

還有,你要照顧饑荒早期預警系統的東西,而冒充

1.要模擬用戶,調用該服務的Web方法之前設置 OrganizationServiceProxy實例來電顯示屬性。

2.用戶(假冒者)必須具有ActOnBehalfOf特權或是PrivUserGroup組的Active Directory中的構件

代碼示例

SystemUser user = null; 
user = new SystemUser(systemUser); 
OrganizationServiceProxy service = CrmService.Proxy; 
service.CallerID = user.Id; 

由於您的代碼不可用請確保以上所有字段設置正確

如需詳細瞭解請使用鏈接 https://crmbusiness.wordpress.com/2015/07/21/crm-2015-understanding-impersonation-in-plugins-and-knowing-when-to-use-it/

+0

如果我們不需要,我們不希望通過組織服務完成此操作,我已經包含了我們如何進行身份驗證的代碼段。請參閱更新後的問題 –

+0

即將更新解決方案。謝謝 – Ramankingdom