首页 文章

使用ADAL通过Angular 2对Dynamics CRM Web API进行未经授权的HTTP请求

提问于
浏览
5

我正在尝试使用Angular创建一个可以通过Web API连接到Dynamics CRM的应用程序 . 这些是我遵循的步骤:

1. 在Azure中注册了本机应用程序,授予了所需的委派权限并更新了清单以允许隐式流 .

2. 在CRM中创建了一个应用程序用户,将其应用程序ID设置为等于我的Azure注册应用程序的客户端ID . 为我的应用程序用户分配了自定义安全角色 .

3. 克隆了许多Angular 2快速启动Git存储库,它通过ADAL与Azure AD进行身份验证,例如this one .

4. 更新了克隆代码的adal配置,设置了我的 tenantclientIdredirectUriendpoints .

到目前为止,这已经成功了 . 我可以通过我的浏览器启动应用程序并登录,作为我的应用程序用户或作为Azure AD一部分的其他CRM用户 . 这会返回一个令牌 .

5. 尝试将 http.get 发送到 v8.0v8.2 (我被告知 v8.2 不支持跨域调用):

getEntities(): Promise<any> {
    let token = this.adalService.getCachedToken(this.adalService.config.clientId);
    let headers = new Headers({
        'Authentication': 'Bearer ' + token,
        'Accept': 'application/json',
        'Content-Type': 'application/json; charset=utf-8',
        'OData-MaxVersion': '4.0',
        'OData-Version': '4.0'
    });
    let options = new RequestOptions({ headers: headers });

    return this.http.get(`${crmURL}/api/data/v8.2/accounts`, options)
        .toPromise()
        .then((res) => { return res; })
        .catch((e) => { console.error(e); });
}

6. 收到此错误消息:

enter image description here

它写道:

No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:3000' is therefore not allowed access. 
The response had HTTP status code 401.

查看我的Chrome浏览器的网络标签,我收到两个回复:

回应1

General

Request URL:https://ms-dyn365-prevxxxxxx/api/data/v8.2/accounts
Request Method:OPTIONS
Status Code:200 OK
Remote Address:104.44.xxx.xxx:xxx
Referrer Policy:no-referrer-when-downgrade

Headers

Access-Control-Allow-Headers:authentication,content-type,odata-maxversion,odata-version
Access-Control-Allow-Methods:GET
Access-Control-Allow-Origin:http://localhost:3000
Access-Control-Expose-Headers:Preference-Applied,OData-EntityId,Location,ETag,OData-Version,Content-Encoding,Transfer-Encoding,Content-Length,Retry-After
Access-Control-Max-Age:3600
Content-Length:0
Date:Thu, 13 Apr 2017 10:08:01 GMT
Server:Microsoft-IIS/8.5
Set-Cookie:crmf5cookie=!NDyiupL55lrWWLtPQKTK52dwbxk9wdEAHeCiec0/z/7x9KWXe2dVIdQCGvL0S/HAp7F3N0OGfeWf/70=;secure; path=/
Strict-Transport-Security:max-age=31536000; includeSubDomains
Vary:Origin
X-Powered-By:ASP.NET

回应2

General

Request URL:https://ms-dyn365-prevxxxxx.crm4.dynamics.com/api/data/v8.2/accounts
Request Method:GET
Status Code:401 Unauthorized
Remote Address:104.xx.xxx.xxx:xxx
Referrer Policy:no-referrer-when-downgrade

Headers

Cache-Control:private
Content-Length:49
Content-Type:text/html
Date:Thu, 13 Apr 2017 10:08:01 GMT
REQ_ID:b2be65bc-xxxx-4b34-xxxx-5c39812650xx
Server:Microsoft-IIS/8.5
Set-Cookie:ReqClientId=xxxxxxxx-70b5-45f9-9b84-30f59481bxxx; expires=Wed, 13-Apr-2067 10:08:01 GMT; path=/; secure; HttpOnly
Strict-Transport-Security:max-age=31536000; includeSubDomains
WWW-Authenticate:Bearer authorization_uri=https://login.windows.net/xxxxxxxx-87e4-4d81-8010-xxxxxxxxxxxxx/oauth2/authorize, resource_id=https://ms-dyn365-prevxxxxxx.crm4.dynamics.com/
X-Powered-By:ASP.NET

Note: 我能够通过Postman成功访问Web API:

1. 我在Azure中为我的应用程序输入 https://www.getpostman.com/oauth2/callback 作为回调URL .

2. 我打开Postman,设置如下参数并按下Request Token:

Token Name: Token
Auth URL: https://login.windows.net/common/oauth2/authorize?resource=https://ms-dyn365-prevxxxxxx.crm4.dynamics.com
Access Token URL: https://login.microsoftonline.com/common/oauth2/token
Client ID: xxxxxxxx-ebd3-429c-9a95-xxxxxxxxxxxx
Callback URL: https://www.getpostman.com/oauth2/callback
Grant Type: Authorization Code

3. 这将打开我登录的网页 .

4. 返回一个令牌,我将其添加到Postman GET标头:

Content-Type: application/json
Authorization: Bearer eyJ0eXAiO...

5. 发送邮递员的GET:

GET https://ms-dyn365-prevxxxxxx.crm4.dynamics.com/api/data/v8.2/accounts

6. 帐户已成功返回 .

如果我在我的应用程序中使用相同的令牌,我仍然会收到401错误 .

1 回答

  • 3

    Access-Control-Allow-Origin 表示问题是由 cross domain 引起的 .

    通常,我们可以在服务器上使用JSONP或设置 Access-Control-Allow-Origin 标头 . 如果JSONP和标头都无法设置,因为服务是第三方提供者,我们还可以创建一个服务代理,允许从特定的orignal调用 .

    有关AJAX跨域问题的更多细节,您可以参考这个thread .

    更新

    在进一步调查之后,问题是服务器端问题,该问题与REST请求的特定版本有关 .

    8.2 版本的REST目前不支持跨域 . 作为一种解决方法,我们可以使用 8.0 ,这对我来说效果很好,如下图所示:

    enter image description here

    将代码演示附加到测试:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <base href="/">
        <title></title>
        <script src="node_modules\angular\angular.js"></script>
    
    </head>
    <body>
        <div ng-app="myApp">
            <div ng-controller="HomeController">
                <ul class="nav navbar-nav navbar-right">            
                         <li><a class="btn btn-link" ng-click="listAccounts()">List account info</a></li>
                </ul>
               <div ng-repeat="account in accounts">
                        <span>name:</span><span>{{account.name}}</span>
               </div>
            </div>
        </div>
    
        <script>
        var myApp = angular.module('myApp',[]);
    
        myApp.controller('HomeController', ['$scope', '$http',
                                function ($scope, $http){
    
                                        $scope.listAccounts=function(){
    
                                            var req = {
                                            method: 'GET',
                                            url: 'https://{domain}.crm.dynamics.com/api/data/v8.0/accounts',
                                            headers: {
                                            'authorization': 'Bearer eyJ0eXAiO...'
                                            }
                                            };
                                           $http(req).then(function(response){
                                                $scope.accounts=response.data.value
                                           }, function(){
    
                                           });
                                        }
                                }]);
        </script>
    </body>
    </html>
    

    为Angular 2附加测试代码示例:

    https://github.com/VitorX/angular2-adaljs-crm

相关问题