【问题标题】:Dynamics 365 for Operations SPA and ODataDynamics 365 for Operations SPA 和 OData
【发布时间】:2017-10-31 19:36:43
【问题描述】:

我正在尝试创建一个单页 Web 应用程序,该应用程序通过 Azure AD 使用 Dynamics 365 for Operations 进行身份验证。我已按照所有说明在 Azure AD 和 Dynamics 365 中注册我的应用程序。但是,当我在 D365 中向 OData 端点发出请求时,我已成功通过 Azure AD 进行身份验证并在我的应用程序中使用 adal javascript 库收到了有效令牌,我收到 401 错误。我通过 Azure AD 进行了身份验证,并且我在身份验证标头中传递了我的令牌,所以我无法弄清楚为什么我会收到身份验证错误,除非我没有正确设置我的授权标头?这是我的要求:

//Function that actually retrieves the accounts
function retrieveAccounts(error, token) {
// Handle ADAL Errors.
if (error || !token) {
    errorMessage.textContent = 'ADAL error occurred: ' + error;
    return;
}

var req = new XMLHttpRequest()
req.open("GET", encodeURI(organizationURI + "/data/Projects"), true);
//Set Bearer token
req.setRequestHeader("Authorization", "Bearer" + token);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
    if (this.readyState == 4 /* complete */) {
        req.onreadystatechange = null;
        if (this.status == 200) {
            var projects = JSON.parse(this.response).value;
            renderProjects(projects);
        }
        else {
            var error = JSON.parse(this.response).error;
            console.log(error.message);
            errorMessage.textContent = error.message;
        }
    }
};
req.send();
}  

任何想法将不胜感激!我能够通过使用 Web api 的 Dynamics 365 CRM 成功地做到这一点,所以我假设它也适用于操作,即使设置有点不同。

【问题讨论】:

  • 嗨,乔希-很好,是的,你是对的。这实际上是代码块中的复制和粘贴错误。你确实需要空间。但是,我后来了解到,D365-Ops 还不支持这种身份验证方法(JavaScript)。 CORS 存在问题,导致调用失败。

标签: azure authentication microsoft-dynamics operations dynamics-365


【解决方案1】:

我认为此方法不起作用,问题是 D365 Operations OData 端点需要使用客户端密码进行身份验证。在此方法中,在对服务的调用中作为不记名令牌传递的 JWT 令牌未使用客户端密钥进行签名。我认为没有任何安全的方法可以从单个 Web 应用程序中执行此操作。我将关闭它,因为我相信答案是创建第二个 Web api 应用程序来处理调用、服务器端并将数据传递回我的 SPA

【讨论】:

    【解决方案2】:

    这看起来像是一个简单的错字:

    //Set Bearer token
    req.setRequestHeader("Authorization", "Bearer " + token);
    

    注意“Bearer”后面的空格

    【讨论】:

      【解决方案3】:

      我也遇到了同样的问题,但在做了一些研究之后,我使用 Web API 与 CRM 的集成终于成功了。

      尝试使用此过程:-

          int                             find;
          real                            inventOnHandQtyval;
          str                             url,aosUri,activeDirectoryTenant;
          str                             activeDirectoryClientAppId;
          str                             activeDirectoryClientAppSecret,json;
          str                             postData,activeDirectoryResource;
          str                             aadClientAppSecret,oAuthHeader;
          str                             prdGUIDCode,prodnum;
          str                             returnValue,jsonString,jsondszstr;
      
          System.Net.HttpWebRequest       request;
          System.Net.HttpWebResponse      response;
          System.Byte[]                   byteArray;
          System.IO.Stream                dataStream;
          System.IO.StreamReader          streamRead;
          System.IO.StreamWriter          streamWrite;
          System.Net.ServicePoint         servicePoint;
          System.Net.ServicePointManager  servicePointmgr;
          System.Net.HttpVersion          version;
          System.Web.Script.Serialization.JavaScriptSerializer jsonSerializer;
          CLRObject                       clrObj;
          Newtonsoft.Json.JsonReader      reader;
          Newtonsoft.Json.Linq.JObject    prod;
      
          System.Text.Encoding            utf8;
          System.Exception                ex;
          Counter                         countCounter;
          Object                          obj;
          Map                             data;
          EcoResProduct                   ecoresproductfetch;
          EcoResProductTranslation        ecoresproductTranslation;
          InventTableModule               inventTableModule;
      
      
      
      
          try
          {
              InventTable     inventtable = sender as InventTable;
      
              System.Net.WebHeaderCollection  headers = new System.Net.WebHeaderCollection();
              var jsonSerializerobj = new  System.Web.Script.Serialization.JavaScriptSerializer();
              prod = new Newtonsoft.Json.Linq.JObject();
              inventOnHandQtyval = InventOnhand::newItemId(inventtable.ItemId).availPhysical();
              select inventTableModule where inventTableModule.ItemId==inventtable.ItemId;
              prod.Add("name",inventtable.itemName());
              prod.Add("productnumber",inventtable.ItemId);
              prod.Add("defaultuomscheduleid@odata.bind","/uomschedules(7F6F7338-1D80-4E90-9110-A70897C73834)");
              prod.Add("defaultuomid@odata.bind","/uoms(68A2E342-E1CA-4CC2-B430-C05057BCE7BC)");
              prod.Add("currentcost",0.00);
              prod.Add("description",inventtable.itemName());
              prod.Add("msdyn_fieldserviceproducttype",690970000);
      
      
              json=Newtonsoft.Json.JsonConvert::SerializeObject(prod);
      
              System.IO.MemoryStream mem = new System.IO.MemoryStream();
      
      
      
              new InteropPermission(InteropKind::ClrInterop).assert();
      
      
      
              headers = new System.Net.WebHeaderCollection();
      
              url = "https://abc.crm4.dynamics.com/api/data/v8.1/details";
      
              clrObj = System.Net.WebRequest::Create(url);
      
              aosUri = "https://login.windows.net/abcd1234/oauth2/authorize?";
      
              activeDirectoryTenant = "https://login.microsoftonline.com/abcd134/oauth2/token";
      
              activeDirectoryClientAppId = "xyz124";
      
      
      
              activeDirectoryResource = "https://abc.crm4.dynamics.com";
      
              Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext authenticationContext =
                                      new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(activeDirectoryTenant);
      
      
      
              var userCredential = new  Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential("abc@xyz.onmicrosoft.com", "abc@1234");
      
              Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult authenticationResult =
                  authenticationContext.AcquireTokenAsync(activeDirectoryResource, activeDirectoryClientAppId, userCredential).Result;
      
      
              headers.Add("Authorization", authenticationResult.CreateAuthorizationHeader());
      
              headers.Add("Prefer", "return=representation");
              request = clrObj;
      
              request.Headers=headers;
      
              utf8 = System.Text.Encoding::get_UTF8();
              byteArray = utf8.GetBytes(json);
              request.set_Method("POST");
              request.set_KeepAlive(true);
      
              request.ContentType="application/json";
      
              request.set_ContentLength(byteArray.Length);
      
      
      
      
      
      
      
              servicePoint = request.get_ServicePoint();
      
              System.Net.ServicePointManager::set_Expect100Continue(false);
      
              System.Net.ServicePointManager::set_SecurityProtocol(System.Net.SecurityProtocolType::Tls12);
      
      
      
              dataStream = request.GetRequestStream();
      
              dataStream.Write(byteArray, 0, byteArray.get_Length());
      
              response = request.GetResponse();
      
      
      
                  dataStream = response.GetResponseStream();
      
      
                  streamRead = new System.IO.StreamReader(dataStream);
      
                  jsonString = streamRead.ReadToEnd();
      
      
      
                  data=RetailCommonWebAPI::getMapFromJsonString(jsonString);
      
                  prdGUIDCode = data.lookup("productid");
      
                  prodnum = data.lookup("productnumber");           
      
          }
      
          catch(Exception::CLRError)
          {
              ex = CLRInterop::getLastException().GetBaseException();
              error(ex.get_Message());
          }
      
      
      
      
      
          dataStream.Close();
      
          response.Close();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-09
        • 2020-05-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多