C# 从Azure函数向Dynamics 365进行身份验证 脚本
我有一个在线托管的Dynamics 365 v9组织。我在我的Dynamics组织的另一个租户上的Azure Function应用程序中托管了一组Azure功能 我是使用Dynamics插件注册工具创建的,在某些事件中(例如在Dynamics中创建联系人时),该工具会通过其端点URL将数据发布到我的Azure函数 Dynamics 365和my Azure函数之间的身份验证是通过在HTTP请求的身份验证HttpHeader中传递C# 从Azure函数向Dynamics 365进行身份验证 脚本,c#,azure,dynamics-crm,azure-functions,dynamics-365,C#,Azure,Dynamics Crm,Azure Functions,Dynamics 365,我有一个在线托管的Dynamics 365 v9组织。我在我的Dynamics组织的另一个租户上的Azure Function应用程序中托管了一组Azure功能 我是使用Dynamics插件注册工具创建的,在某些事件中(例如在Dynamics中创建联系人时),该工具会通过其端点URL将数据发布到我的Azure函数 Dynamics 365和my Azure函数之间的身份验证是通过在HTTP请求的身份验证HttpHeader中传递x-Functions-key值来实现的 Azure函数从Dynam
x-Functions-key
值来实现的
Azure函数从Dynamics中的事件接收数据,数据形式为a,我可以使用以下代码读取:
using System.Net;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
var jsonContent = await req.Content.ReadAsStringAsync();
log.Info(jsonContent);
return req.CreateResponse(HttpStatusCode.OK);
}
使用System.Net;
公共静态异步任务运行(HttpRequestMessage请求、TraceWriter日志)
{
var jsonContent=await req.Content.ReadAsStringAsync();
log.Info(jsonContent);
返回请求CreateResponse(HttpStatusCode.OK);
}
问题
Azure功能如何通过调用Dynamics 365组织的身份验证来读取和写入数据
我试过的
jsonContent
字符串的一个对象称为ParentContext
。也许这可以被重用以向调用Dynamics的组织进行身份验证
Marc Schweigert建议使用S2S,并向其存储库提供了一个示例。如果我能让这种方法发挥作用,我会在这里发布解决方案。这也是我很好奇的事情,但我还没有机会对此进行实验 对于第二种选择,您是否已在目标AAD中注册申请并授予同意 当他们授予许可时,您注册的应用程序将添加到Azure AD企业应用程序列表中,Azure AD租户的用户可以使用该应用程序 只有在管理员授予许可后,您才能在订阅服务器的Dynamics 365租户中创建应用程序用户 我认为访问问题的根源与应用程序的服务主体对象(目标租户的本地对象)有关 服务主体对象 为了访问由Azure AD租户保护的资源,需要访问的实体必须由安全主体表示。用户(用户主体)和应用程序(服务主体)都是如此。安全主体定义该租户中用户/应用程序的访问策略和权限。这将启用核心功能,例如登录期间的用户/应用程序身份验证,以及资源访问期间的授权 将应用程序对象视为应用程序的全局表示形式,以便在所有租户中使用,将服务主体视为本地表示形式,以便在特定租户中使用 嗯
-克里斯这也是我很好奇的事情,但我还没有机会对此进行实验 对于第二种选择,您是否已在目标AAD中注册申请并授予同意 当他们授予许可时,您注册的应用程序将添加到Azure AD企业应用程序列表中,Azure AD租户的用户可以使用该应用程序 只有在管理员授予许可后,您才能在订阅服务器的Dynamics 365租户中创建应用程序用户 我认为访问问题的根源与应用程序的服务主体对象(目标租户的本地对象)有关 服务主体对象 为了访问由Azure AD租户保护的资源,需要访问的实体必须由安全主体表示。用户(用户主体)和应用程序(服务主体)都是如此。安全主体定义该租户中用户/应用程序的访问策略和权限。这将启用核心功能,例如登录期间的用户/应用程序身份验证,以及资源访问期间的授权 将应用程序对象视为应用程序的全局表示形式,以便在所有租户中使用,将服务主体视为本地表示形式,以便在特定租户中使用 嗯
-克里斯我没想到你能明智地使用“真实”用户凭据连接到CRM 我将使用服务帐户连接回CRM。创建新的CRM 用户,尤其是出于此目的,如果您使用户非交互式,则不应使用许可证。然后,您可以使用该服务帐户的凭据使用
CrmServiceClient
连接到CRM。或者看一看
如果您能够向功能应用程序提供用户id,则可以通过CRM web服务向“真实”用户使用服务帐户
要模拟用户,请在的实例上设置CallerId属性
OrganizationServiceProxy,然后调用服务的Web方法
我没想到你能明智地使用“真实”用户凭据连接到CRM 我将使用服务帐户连接回CRM。创建新的CRM 用户,尤其是出于此目的,如果您使用户非交互式,则不应使用许可证。然后可以使用c
string odataUrl = "https://org.crm6.dynamics.com/api/data/v8.2/"; // trailing slash actually matters
string appId = "some-guid";
string clientSecret = "some key";
AuthenticationParameters authArg = AuthenticationParameters.CreateFromResourceUrlAsync(new Uri(odataUrl)).Result;
AuthenticationContext authCtx = new AuthenticationContext(authArg.Authority);
AuthenticationResult authRes = authCtx.AcquireTokenAsync(authArg.Resource, new ClientCredential(appId, clientSecret)).Result;
using (HttpClient client = new HttpClient()) {
client.TimeOut = TimeSpan.FromMinutes (2);
client.DefaultRequestHeaders.Add("Authorization", authRes.CreateAuthorizationHeader ());
using (HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, $"{odataUrl}accounts?$select=name&$top=10")) {
using (HttpResponseMessage res = client.SendAsync(req).Result) {
if (res.IsSuccessStatusCode) {
Console.WriteLine(res.Content.ReadAsStringAsync().Result);
}
else {
// cry
}
}
}
}
string odataUrl = "https://org.crm6.dynamics.com/xrmservices/2011/organization.svc/web?SdkClientVersion=8.2"; // don't question the url, just accept it.
string appId = "some-guid";
string clientSecret = "some key";
AuthenticationParameters authArg = AuthenticationParameters.CreateFromResourceUrlAsync(new Uri(odataUrl)).Result;
AuthenticationContext authCtx = new AuthenticationContext(authArg.Authority);
AuthenticationResult authRes = authCtx.AcquireTokenAsync(authArg.Resource, new ClientCredential(appId, clientSecret)).Result;
using (OrganizationWebProxyClient webProxyClient = new OrganizationWebProxyClient(new Uri(orgSvcUrl), false)) {
webProxyClient.HeaderToken = authRes.AccessToken;
using (OrganizationServiceContext ctx = new OrganizationServiceContext((IOrganizationService)webProxyClient)) {
var accounts = (from i in ctx.CreateQuery("account") orderby i["name"] select i).Take(10);
foreach (var account in accounts)
Console.WriteLine(account["name"]);
}
}
var clientcred = new ClientCredential(clientId, clientSecret);
AuthenticationContext authContext = new AuthenticationContext(aadInstance, false);
AuthenticationResult result = authContext.AcquireToken(organizationUrl, clientcred);
token = result.AccessToken;
ExpireDate = result.ExpiresOn.DateTime;
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);