19

Byliśmy udane w użyciu OData v8.1 końcowym w 2016 do impersonate a user.jak personifikować użytkownika poprzez OData

Należy pamiętać, że prośba jest przeznaczony przepływu: Postman -> host_lokalny Microservice -> CRM

Przykład wniosku roboczego od Postman -> CRM (bezpośrednio, bez przechodzenia przez microservice)

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 

Przeciwko OData końca Temperatura: ..../api/data/v8.1/leads

Zauważ, że ta odniosła sukces tylko wtedy, gdy wydane bezpośrednio przed końcowym OData V8.1 poprzez postman.

Podczas próby zrobienia tego samego, mając usługę uruchomioną lokalnie (Listonosz -> Usługa LocalHost -> CRM), to się nie udaje i po prostu ignoruje ??? nagłówek MSCRMCallerID.

Po zbadaniu nagłówków, które zostały przekazane do localhost Microservice od Postman, wniosek, jako zbadane przez debugger w 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 
}} 

Rekord jest tworzony pomyślnie, jednak na polu CreatedBy jest usługa nazwa użytkownika NIE nazwa użytkownika MSCRMCallerID (d994d6ff-5531-e711-9422-00155dc0d345), a pole CreatedOnBehalf jest puste.

Co robimy źle?

Jak możemy uzyskać to podszywanie się od naszych usług?

EDIT + Więcej informacji

Należy pamiętać, że wierzę, że podaję wszystkie istotne informacje, ale jeśli nie, proszę dać mi znać, co inne wejście powinien zapewnić w tej sprawie .

Co próbowałem?

  1. zmienił kolejność nagłówków
  2. grał z przypadku nagłówków
  3. zapewniony że GUID jest poprawna od użytkownika do podszywania
  4. zapewnić, że użytkownik ma zarówno delegata i sys rolę administratora (chociaż nie ma to znaczenia, ponieważ działa to podczas wykonywania żądania bezpośrednio przed punktem końcowym crm odata, a nie punktem końcowym, który nasza usługa wystawia
  5. próbowały wykonać żądanie zarówno z https, jak i http
  6. skrzypek ślad jak pokazano poniżej

Należy pamiętać, że ten ślad Skrzypek ma śladu pokazując Postman -> Microservice żądania. To nie pokazuje komunikacji z localhost microservice do CRM. (nie jestem pewien dlaczego, może dlatego, że jest szyfrowana)

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 zasugerował, że korzystanie z usługi organizacji w celu uwierzytelnienia, jest to opcja, zważywszy realizujemy przeciwko Web API? Czy żądany token nadal będzie ważny. (Należy pamiętać, że może to być głupie pytanie, a powodem jest to, że nie rozumiem, jak działa uwierzytelnianie).

Poniżej znajduje się fragment kodu z jak jesteśmy autentyczną obecnie na każde wezwanie:

//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

Czy udało Ci się zweryfikować nagłówek w zakładce sieci skrzypka lub przeglądarki? –

+0

@ArunVinoth dziękuję za twoje pytanie, zaktualizowałem pytanie –

+0

czy byłeś w stanie to rozwiązać? –

Odpowiedz

3

Kiedy robisz Postman na żądanie CRM, jego bezpośrednie połączenie & CRM obsługuje to w oczekiwanym sposób.

Ale w Postman -> Microservice -> CRM, nagłówek gubi się między Microservice a CRM.

W urządzeniu Microservice należy ręcznie obsłużyć nagłówek do wywołania CRM SDK.

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

Albo HTTP Header Forwarding (Niestety nie mogłem znaleźć jeden dla Azure/C#)

enter image description here

Aktualizacja:

Am zakładając, że są po tej MSDN samples zrobić swoją CRM połączenia Web API w mikroserwisie C#. Zawarłem nasz nagłówek w potrzebie - MSCRMCallerID. Sprawdź, czy to ci pomaga.

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

Jest to bardzo dobra hipoteza, ale sprawdziłem nagłówki wysyłane z usługi do CRM. Wprowadziłem punkt przerwania tuż przed wydaniem przez Microsoft naszej prośby o CRM, a ja zajrzałem do wniosku i pokazuje, że pożądany Kapelusznik rzeczywiście znajduje się wewnątrz żądania. Nie mogę być w 100% pewny, że nagłówek nie zostanie utracony, ponieważ nie udało mi się zrobić śladu w Skrzypku, ponieważ Skrzypek blokuje localhost. –

+0

Miałem na myśli Microservice, a nie Microsoft w pierwszym komentarzu –

+0

świetnie, że już go debugowałeś i byłeś pewien. –

0

Istnieje fews rzeczy, które trzeba dbać podczas podszywanie

1. Aby personifikować użytkownika, należy ustawić właściwość rozmówcy na wystąpienie OrganizationServiceProxy przed wywołaniem metody internetowych Serwisu.

2. Użytkownik (odtwórca) musi mieć przywilej ActOnBehalfOf lub być członkiem grupy PrivUserGroup w Active Directory

przykładowy kod

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

Ponieważ kod nie jest proszę upewnić się, że wszystkie powyższe pola są ustawione prawidłowo

Aby poznać szczegóły, użyj linka https://crmbusiness.wordpress.com/2015/07/21/crm-2015-understanding-impersonation-in-plugins-and-knowing-when-to-use-it/

+0

nie chcemy tego robić za pośrednictwem usługi org, jeśli nie musimy tego robić, dodałem fragment kodu potwierdzający autentyczność. zobacz zaktualizowane pytanie –

+0

zaktualizuje wkrótce rozwiązanie. Dzięki – Ramankingdom