c# - valid - cómo hacerse pasar por un usuario a través de odata
summary documentation c# (2)
Cuando está realizando una solicitud de Postman a CRM, su llamada directa y CRM se maneja de la manera esperada.
Pero en Postman -> Microservice -> CRM, el encabezado se pierde entre Microservice a CRM.
En su Microservicio, debe manejar el encabezado para reenviar manualmente a la llamada SDK de CRM.
HttpWebRequest myHttpWebRequest1= (HttpWebRequest)WebRequest.Create(uri);
myHttpWebRequest1.Headers.Add("MSCRMCallerID", "D994D6FF-5531-E711-9422-00155DC0D345");
O Reenvío de encabezado HTTP (Lo siento, no pude encontrar uno para Azure / C #)
Actualizar:
Supongo que está siguiendo estas muestras de MSDN para hacer su llamada a la API web de CRM en c # microservice. He incluido nuestro encabezado en necesidad - MSCRMCallerID. A ver si te ayuda.
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);
}
}
Hemos tenido éxito al utilizar el punto final odata v8.1 en 2016 para hacerse pasar por un usuario.
Tenga en cuenta que el flujo de solicitud previsto es: Postman -> LocalHost Microservice -> CRM
Ejemplo de una solicitud de trabajo de Postman -> CRM (directamente, sin pasar por el microservicio)
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
Contra el punto final de odata: ..../api/data/v8.1/leads
Tenga en cuenta que esto solo tuvo éxito cuando se emitió directamente contra el punto final de odata v8.1 a través del postman .
Al intentar hacer lo mismo, tener un servicio ejecutándose localmente (Postman -> LocalHost Service -> CRM) , esto falla, y simplemente lo ignora ??? el encabezado MSCRMCallerID.
Al examinar los encabezados que se pasaron al LocalHost Microservice de Postman, la solicitud, tal como lo examinó el depurador en 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
}}
El registro se creó con éxito, sin embargo, en el campo CreatedBy está el nombre de usuario del servicio NO el nombre de usuario de MSCRMCallerID (d994d6ff-5531-e711-9422-00155dc0d345), y el campo CreatedOnBehalf está vacío.
¿Qué estamos haciendo mal?
¿Cómo conseguimos que esta suplantación funcione desde nuestro servicio?
EDITAR + Más información
Tenga en cuenta que creo que he incluido toda la información relevante, pero si no lo he hecho, hágame saber qué otra información debo proporcionar sobre este tema.
¿Qué he intentado?
- cambiado el orden de los encabezados
- Jugó con el caso de los encabezados.
- Aseguró que el guid es correcto del usuario por suplantación.
- aseguró que el usuario tenga tanto el rol de administrador delegado como de administrador del sistema (aunque esto es irrelevante porque esto funciona cuando se ejecuta la solicitud directamente contra el punto final de crm odata, en lugar del punto final que expone nuestro servicio
- han intentado ejecutar la solicitud tanto en https Y http
- rastro de violinista como se muestra abajo
Tenga en cuenta que esta traza del fiddler es una traza que muestra la solicitud de microservicio Postman -> . No muestra la comunicación del microservicio de host local a CRM. (No estoy seguro de por qué, tal vez porque está cifrado)
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 ha sugerido que usemos el servicio de la organización para autenticarnos. ¿ Es esta una opción, considerando que estamos ejecutando contra la API web? ¿Seguirá siendo válido el token solicitado? (Tenga en cuenta que esta puede ser una pregunta tonta, y la razón es porque no entiendo cómo funciona la autenticación).
El siguiente es un fragmento de código de cómo nos estamos autentificando actualmente en cada llamada :
//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.");
}
Hay pocas cosas que debes tener en cuenta mientras te personificas
1. Para hacerse pasar por un usuario, establezca la propiedad CallerId en una instancia de OrganizationServiceProxy antes de llamar a los métodos web del servicio.
2. El usuario (imitador) debe tener el privilegio ActOnBehalfOf o ser miembro del grupo PrivUserGroup en Active Directory
Ejemplo de código
SystemUser user = null;
user = new SystemUser(systemUser);
OrganizationServiceProxy service = CrmService.Proxy;
service.CallerID = user.Id;
Dado que su código no está disponible, asegúrese de que todos los campos anteriores estén configurados correctamente
Para una comprensión más detallada, utilice el enlace https://crmbusiness.wordpress.com/2015/07/21/crm-2015-understanding-impersonation-in-plugins-and-knowing-when-to-use-it/