Dynamics CRM 2015/2016 Web API:验证和授权

在上篇文章里面我给大家展示了一些如果使用Web API进行业务处理的URL,让大家对这套新的API有个感性的认识,那么今天,我们来看看怎么在重客户端(非浏览器脚本)下怎么完成权限的授予和验证。

相对于轻客户端(浏览器脚本),在重客户端环境下调用CRM Web API需要考虑权限验证的细节,还好微软已经给我们提供了SDK,免去重复发明轮子的烦恼,让我们有更多的精力放在业务逻辑的实现上面。下面我给大家演示一下怎么在重客户端下完成授权和验证,并调用Create API创建一条客户记录。


首先给大家介绍一下微软为我们提供的授权和验证辅助类,当然下面这个类被我做了微调,这样它就能支持更加复杂的调用场景,比如:CRM Online环境。

// =====================================================================
//  This file is part of the Microsoft Dynamics CRM SDK code samples.
//
//  Copyright (C) Microsoft Corporation.  All rights reserved.
//
//  This source code is intended only as a supplement to Microsoft
//  Development Tools and/or on-line documentation.  See these other
//  materials for detailed information regarding Microsoft code samples.
//
//  THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//  PARTICULAR PURPOSE.
// =====================================================================
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security;
using System.Configuration;

namespace Microsoft.Crm.Sdk.Samples.HelperCode
{
    /// <summary>
    /// Manages user authentication with the Dynamics CRM Web API (OData v4) services. This class uses Microsoft Azure
    /// Active Directory Authentication Library (ADAL) to handle the OAuth 2.0 protocol. 
    /// </summary>
  public class Authentication
    {
        #region Constructors
        private string _clientId = null;
        private string _service = null;
        private string _redirectUrl = null;
        private string _username = null;
        private string _password = null;

        //private Configuration _config;

        /// <summary>
        /// Establishes an authenticaion session for the service.
        /// </summary>
        /// <param name="config">A populated configuration object.</param>
        //public Authentication(Configuration config)
        //    : this(config.ClientId, config.ServiceUrl, config.RedirectUrl)
        //{
        //    _config = config;
        //}

        /// <summary>
        /// Establishes an authenticaion session for the service.
        /// </summary>
        /// <param name="clientId">The client ID of an Azure Active Directory registered app.</param>
        /// <param name="service">The URL of the CRM server root address. For example: https://mydomain.crm.dynamics.com</param>
        /// <param name="redirect">The redirect URL of an Azure Active Directory registered app.</param>
        public Authentication(String clientId, String service, String redirect, String username, String password)
        {
            _clientId = clientId;
            _service = service;
            _redirectUrl = redirect;
            _username = username;
            _password = password;

            _context = new AuthenticationContext(Authority, false);
        }
        #endregion Constructors

        #region Properties
        private AuthenticationContext _context = null;
        private string _authority = null;

        /// <summary>
        /// The authentication context.
        /// </summary>
        public AuthenticationContext Context
        { get { return _context; } }

        /// <summary>
        /// The URL of the authority to be used for authentication.
        /// </summary>
        public string Authority
        {
            get
            {
                if (_authority == null)
                    DiscoverAuthority(_service);

                return _authority;
            }

            set { _authority = value; }
        }
        #endregion Properties

        #region Methods
        /// <summary>
        /// Returns the authentication result for the configured authentication context.
        /// </summary>
        /// <returns>The refreshed access token.</returns>
        /// <remarks>Refresh the access token before every service call to avoid having to manage token expiration.</remarks>
        public AuthenticationResult AcquireToken()
        {
            if (!string.IsNullOrEmpty(_username) && !string.IsNullOrEmpty(_password))
            {
                UserCredential cred = new UserCredential(_username, _password);
                return _context.AcquireToken(_service, _clientId, cred);
            }
            return _context.AcquireToken(_service, _clientId, new Uri(_redirectUrl));
        }

        /// <summary>
        /// Returns the authentication result for the configured authentication context.
        /// </summary>
        /// <param name="username">The username of a CRM system user in the target organization. </param>
        /// <param name="password">The password of a CRM system user in the target organization.</param>
        /// <returns>The authentication result.</returns>
        /// <remarks>Setting the username or password parameters to null results in the user being prompted to
        /// enter logon credentails. Refresh the access token before every service call to avoid having to manage
        /// token expiration.</remarks>
        public AuthenticationResult AcquireToken(string username, SecureString password)
        {

            try
            {
                if (!string.IsNullOrEmpty(username) && password != null)
                {
                    UserCredential cred = new UserCredential(username, password);
                    return _context.AcquireToken(_service, _clientId, cred);
                }
            }
            catch (Exception e)
            {
                throw new Exception("Authentication failed. Verify the configuration values are correct.", e);
            }
            return null;
        }


        /// <summary>
        /// Discover the authentication authority.
        /// </summary>
        /// <param name="serviceUrl">The URL of the CRM server root address. For example: https://mydomain.crm.dynamics.com</param>
        public void DiscoverAuthority(String serviceUrl)
        {
            try
            {
                AuthenticationParameters ap = AuthenticationParameters.CreateFromResourceUrlAsync(new Uri(serviceUrl + "/api/data/")).Result;

                if (!String.IsNullOrEmpty(ap.Resource))
                {
                    _service = ap.Resource;
                }
                _authority = ap.Authority;
            }
            catch (HttpRequestException e)
            {
                throw new Exception("An HTTP request exception ocurred during authority discovery.", e);
            }
        }
        #endregion Methods
    }
}

它的使用也非常的简单,只需要通过少数几行代码就可以获得当前用户的AccessToken。我们在拿到这个Token后,只需要将其添加进Http的header集合里面,则可以为当前请求进行授权处理:

  Authentication auth = new Authentication(clientId, service, redirectUrl, username, password);

            //create an account
            JObject acc = new JObject();
            acc.Add("name", "this account was created by WEB API");

            HttpRequestMessage createReq = new HttpRequestMessage(HttpMethod.Post, string.Format("api/data/accounts"));
            createReq.Content = new StringContent(JsonConvert.SerializeObject(acc), Encoding.UTF8, "application/json");
            createReq.Headers.Authorization = new AuthenticationHeaderValue("Bearer", auth.AcquireToken().AccessToken);

            HttpResponseMessage createResponse = await client.SendAsync(createReq).ConfigureAwait(false);

            string accountUri = string.Empty;
            if (createResponse.IsSuccessStatusCode)
            {
                var result = await createResponse.Content.ReadAsStringAsync();
                accountUri = createResponse.Headers.GetValues("OData-EntityId").FirstOrDefault();
            }

是不是很简单呢? 简单的说,我们现在做的事情,类似于构造API访问代理,有了这个代理,我们就能对服务器上的数据进行操作啦,大家赶紧试试吧!

你可能感兴趣的:(Dynamics CRM 2015/2016 Web API:验证和授权)