【问题标题】:How do I connect a server service to Dynamics Online如何将服务器服务连接到 Dynamics Online
【发布时间】:2016-03-22 17:04:11
【问题描述】:

我正在修改一个内部管理应用程序以连接到我们在线托管的 Dynamics 2016 实例。

根据一些在线教程,我一直在使用 SDK 中的 Microsoft.Xrm.Sdk.Client 中的 OrganizationServiceProxy

这似乎需要用户名和密码才能连接,效果很好,但我想以某种不需要特定用户帐户详细信息的方式进行连接。我认为我看到的 OAuth 示例不合适,因为没有 UI,也没有实际的人来显示 OAuth 请求。

public class DynamicsHelper
{
    private OrganizationServiceProxy service;

    public void Connect(string serviceUri, string username, string password)
    {
            var credentials = new ClientCredentials();
            credentials.UserName.UserName = username;
            credentials.UserName.Password = password;

            var organizationUri = new Uri(serviceUri);
            this.service = new OrganizationServiceProxy(organizationUri, null, credentials, null);
    }
}

有没有办法连接应用程序令牌或 API 密钥?

【问题讨论】:

  • 我从未见过不需要凭据的连接代码,但我会从 SDK 中查看这两个页面:msdn.microsoft.com/en-us/library/gg334502.aspxmsdn.microsoft.com/en-us/library/mt595799.aspx
  • 第二个并不真正相关 - 正如我所说,这不是网页或任何可以向用户呈现 OAuth 请求的东西。我想最坏的情况是我们必须为管理服务创建一个虚拟用户,尽管这会产生相关成本。
  • 如果没有用户,您将无法访问 CRM 中的任何内容;此外,应该至少有一个与用户相关联的角色被视为活动角色。当您创建一个连接到将在单个 Active Directory 中工作的 CRM 的应用程序时,您将不需要在连接字符串中指定密码,因为该应用程序将代表添加到 CRM 的用户之一运行系统。所以,即使在这里,你仍然需要用户。问:你为什么不想拥有他?
  • 这是一个自动服务器服务,在后台运行以集成到 Dynamics。通常,我过去创建的这些类型的集成不使用“真实”用户帐户,因为该帐户可能会过期,用户可以离开或更改他们的密码等。通常有一个服务帐户的工具,或者API 密钥或其他一些非人工凭据。如果我需要创建一个完全许可的用户,我可以,这似乎值得确认,因为这不是我必须为任何其他网络服务做的事情。
  • 您能找到解决方案吗?我遇到了同样的问题,如果您能够弄清楚并将解决方案作为答案发布,那就太好了!

标签: c# dynamics-crm dynamics-crm-2016


【解决方案1】:

我发现要成功执行此操作,您需要设置以下所有内容:

  1. 在 Azure AD 中创建应用程序注册:
    • 为其授予 Dynamics API 权限,特别是“以组织用户身份访问 Dynamics 365”
    • 给它一个虚拟的网络重定向URI,例如http://localhost/auth
    • 生成客户端密码并保存以备后用
  2. 在 Azure AD 中创建一个用户帐户并为其授予 Dynamics 权限。
  3. 在 Dynamics 中使用与上述非交互式用户帐户相同的电子邮件创建应用程序用户记录。
  4. 使用您创建的用户帐户验证您的应用程序。

对于第 4 步,您需要打开一个新的隐身窗口,使用以下模式构建一个 url,并在第 2 步中使用您的用户帐户凭据登录:

https://login.microsoftonline.com/<your aad tenant id>/oauth2/authorize?client_id=<client id>&response_type=code&redirect_uri=<redirect uri from step 1>&response_mode=query&resource=https://<organization name>.<region>.dynamics.com&state=<random value>

完成后,您应该会看到您的 Dynamics 应用程序用户具有应用程序 ID 和应用程序 ID URI。

现在,使用您的 ClientId 和 ClientSecret 以及其他一些组织特定变量,您可以使用 Azure Active Directory (AAD) 进行身份验证以获取 oauth 令牌并构造 OrganizationWebProxyClient。我从来没有找到这样做的完整代码示例,但我出于自己的目的开发了以下代码。请注意,您获得的令牌的有效期为 1 小时。

internal class ExampleClientProvider
{
    // Relevant nuget packages:
    // <package id="Microsoft.CrmSdk.CoreAssemblies" version="9.0.2.9" targetFramework="net472" />
    // <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="4.5.1" targetFramework="net461" />

    // Relevant imports:
    // using Microsoft.IdentityModel.Clients.ActiveDirectory;
    // using Microsoft.Crm.Sdk.Messages;
    // using Microsoft.Xrm.Sdk;
    // using Microsoft.Xrm.Sdk.Client;
    // using Microsoft.Xrm.Sdk.WebServiceClient;

    private const string TenantId = "<your aad tenant id>";                 // from your app registration overview "Directory (tenant) ID"
    private const string ClientId = "<your client id>";                     // from your app registration overview "Application (client) ID"
    private const string ClientSecret = "<your client secret>";             // secret generated in step 1
    private const string LoginUrl = "https://login.microsoftonline.com";    // aad login url
    private const string OrganizationName = "<your organization name>";     // check your dynamics login url, e.g. https://<organization>.<region>.dynamics.com
    private const string OrganizationRegion = "<your organization region>"; // might be crm for north america, check your dynamics login url    

    private string GetServiceUrl()
    {
        return $"{GetResourceUrl()}/XRMServices/2011/Organization.svc/web";
    }

    private string GetResourceUrl()
    {
        return $"https://{OrganizationName}.api.{OrganizationRegion}.dynamics.com";
    }

    private string GetAuthorityUrl()
    {
        return $"{LoginUrl}/{TenantId}";
    }

    public async Task<OrganizationWebProxyClient> CreateClient()
    {
        var context = new AuthenticationContext(GetAuthorityUrl(), false);
        var token = await context.AcquireTokenAsync(GetResourceUrl(), new ClientCredential(ClientId, ClientSecret));

        return new OrganizationWebProxyClient(new Uri(GetServiceUrl()), true)
        {
            HeaderToken = token.AccessToken,
            SdkClientVersion = "9.1"
        };
    }

    public async Task<OrganizationServiceContext> CreateContext()
    {
        var client = await CreateClient();
        return new OrganizationServiceContext(client);
    }

    public async Task TestApiCall()
    {
        var context = await CreateContext();

        // send a test request to verify authentication is working
        var response = (WhoAmIResponse) context.Execute(new WhoAmIRequest());
    }
}

【讨论】:

    【解决方案2】:

    使用 Microsoft Dynamics CRM Online 或面向 Internet 的部署 当您使用 CRM Online 的 Web API 或面向 Internet 的本地部署 (IFD) 时 您必须使用 OAuth,如使用 OAuth 连接到 Microsoft Dynamics CRM Web 服务中所述。

    在您可以使用 OAuth 身份验证连接 CRM Web 服务之前, 您的应用程序必须先注册到 Microsoft Azure Active Directory。 Azure Active Directory 用于验证您的应用程序是否被允许访问存储在 CRM 租户中的业务数据。

     // TODO Substitute your correct CRM root service address, 
     string resource = "https://mydomain.crm.dynamics.com";
    
    // TODO Substitute your app registration values that can be obtained after you
    // register the app in Active Directory on the Microsoft Azure portal.
    string clientId = "e5cf0024-a66a-4f16-85ce-99ba97a24bb2";
    string redirectUrl = "http://localhost/SdkSample";
    
    
    // Authenticate the registered application with Azure Active Directory.
    AuthenticationContext authContext = 
        new AuthenticationContext("https://login.windows.net/common", false);
    AuthenticationResult result = 
        authContext.AcquireToken(resource, clientId, new Uri(redirectUrl));
    

    P.S:关于您的方法,最佳实践是将密码存储为明文、加密或加密配置部分最大的安全性。

    See walkhrough here

    希望这会有所帮助:)

    【讨论】:

      【解决方案3】:

      如果我正确理解您的问题,您希望通过已注册的 Azure 应用程序使用 ClientId 和 Secret(而不是用户名和密码)连接到 Dynamics 2016 (Dynamics 365)。如果这是正确的,是的,OrganizationWebProxyClient 可以做到这一点。您甚至可以使用强类型程序集。

      var organizationWebProxyClient = new OrganizationWebProxyClient(GetServiceUrl(), true);
      organizationWebProxyClient.HeaderToken = authToken.AccessToken;
      
      OrganizationRequest request = new OrganizationRequest()
      {
          RequestName = "WhoAmI"
      };
      
      WhoAmIResponse response = organizationWebProxyClient.Execute(new WhoAmIRequest()) as WhoAmIResponse;
      Console.WriteLine(response.UserId);
      
      Contact contact = new Contact();
      contact.EMailAddress1 = "jennie.whiten@mycompany.com";
      contact.FirstName = "Jennie";
      contact.LastName = "White";
      contact.Id = Guid.NewGuid();
      
      organizationWebProxyClient.Create(contact);
      

      获取AccessToken请参考以下帖子Connect to Dynamics CRM WebApi from Console Application

      替换第 66 行(完整源代码)

      authToken = await authContext.AcquireTokenAsync(resourceUrl, clientId, new Uri(redirectUrl), new PlatformParameters(PromptBehavior.Never));
      

      authToken = await authContext.AcquireTokenAsync( resourceUrl, new ClientCredential(clientId, secret));
      

      您还可以查看以下链接 Authenticate Azure Function App to connect to Dynamics 365 CRM online,该链接描述了如何使用 Azure Key Vault 保护您的凭据。

      【讨论】:

        猜你喜欢
        • 2012-07-22
        • 2011-03-18
        • 1970-01-01
        • 2012-12-21
        • 2016-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-13
        相关资源
        最近更新 更多