Internet-API-Hilfecode: Authentifizierungsklasse
Veröffentlicht: Januar 2017
Gilt für: Dynamics 365 (online), Dynamics 365 (on-premises), Dynamics CRM 2016, Dynamics CRM Online
Verwenden Sie die Authentication-Klasse, die im überprüften Einrichten einer Verbindung mit einem Webdienst Microsoft Dynamics 365 unterstützt. Diese Klasse unterstützt zwei Authentifizierungsprotokolle: Windows-Authentifizierung Dynamics 365 für lokal bzw. OAuth 2,0 für Dynamics 365 (Online) oder Bereitstellungen mit Internetzugriff (IFDs). Diese Klasse basiert auf der Authentifizierungs-Bibliothek Microsoft Azure Active Directory (ADAL), um OAuth-Protokolle zu bearbeiten.
Die Authentication-Klasse ist neu in der Authentication.cs Datei in der CRM-SDK Web API Hilfe-Bibliothek Er wurde entworfen, um in Verbindung mit der Configuration Hilfsklassenhierarchie zu arbeiten, damit Sie eine sichere Verbindung mit Ihrem Dynamics 365-Service über ein Objekt vom Typ System.Net.Http einrichten.HttpMessageHandler Weitere Informationen finden Sie unter Verwenden Sie die Microsoft Dynamics 365 WEB API Hilfe-Bibliothek (C#).
Authentifizierungsprozess
Die Funktion, die die Authentication-Klasse verwendet, um einen Dynamics 365-Service zu authentifizieren, hängt von den Informationen ab, die Sie dem Konstruktor mit dem Configuration-Parameter weitergeben. Es versucht, ein HttpMessageHandler-abgeleitetes Objekt zu erstellen, das Sie verwenden können, um eine System.Net. HttpClient-Instanz zu instantiieren, um sichere, dauerhafte Kommunikationssitzungen mit dem Dynamics 365-Service bereitzustellen.
Zuerst wird ein kurzer Discoveryhandshake mit dem angegebenen Dynamics 365-Service ausgeführt, um zu bestimmen, ob OAuths oder die Windows systemeigene Authentifizierung verwendet wird.
Wenn OAuth verwendet wird, wird ein OAuthMessageHandler-Objekt mit der Authentifizierungsbehörde erstellt, die im Handshake ermittelt wurde. Diese Klasse, die von System.Net.Http.DelegatingHandler abgeleitet wird, aktualisiert den OAuth-Zugangstoken bei jeder Anforderung, sodass Sie den Tokenablauf nicht explizit verwalten müssen.
Wenn Windows-Authentifizierung verwendet und die Benutzeranmeldeinformationen angegeben werden, werden anschließend jene Anmeldeinformationen verwendet, um einen HttpClientHandler zu erstellen
Wenn Windows-Authentifizierung verwendet wird, aber die Benutzeranmeldeinformationen nicht bereitgestellt wird, wird ein HttpClientHandler mit den standardmäßigen Netzwerkanmeldeinformationen erstellt.
Klassenhierarchie und -mitglieder
Die folgende Tabelle gibt Aufschluss über öffentliche Mitglieder der Authentication-Klasse.
Authentifizierungsklasse Eigenschaften: Authority – Die URL des Servers, die die OAuth-Authentifizierung verwaltet. ClientHandler – Der HttpMessageHandler, der vom Objekt abgeleitet ist, der die Netzwerkanmeldeinformationen oder den Autorisierungszugriffstoken für Nachrichtenanforderungen bereitstellt. Context –, die für AuthenticationContext ein Authentifizierungsereignis ist.
AquireToken – für OAuth, gibt ein AuthenticationResult zurück, das den aktualisierten Token und den Zugriffstoken für den aktuellen Authentifizierungskontext enthält. Authentication initialisiert eine Instanz dieser Klasse mithilfe des Configuration-Parameters. DiscoverAuthority – Authentifizierungsbehörde des Upgradeplans des Dynamics 365-Webdiensts.
OAuthMessageHandler-Klasse Diese geschachtelte Klasse legt die Autorisierungskopfzeile für jede gesendete Nachricht für Dynamics 365 (Online) und die IFD-Bereitstellung fest. |
Verwendung
Die Configuration und Authentication-Klassen sind so konzipiert, dass sie im Tandem verwendet werden, um eine sichere Verbindung zum Ziel Dynamics 365-Service einzurichten. Erstellen Sie zuerst ein Objekt vom Typ Configuration, und führen ihn als einzelnen Parameter für den Authentication-Konstruktor fort. Nach der erfolgreichen Erstellung können Sie die ClientHandler-Eigenschaft verwenden, um eine sichere, authentifizierte, dauerhafte HTTP Client-Verbindung zum Dynamics 365-Service herzustellen.
Eine gebräuchliche Möglichkeit, um diesen Vorgang zu erzielen, der durch die meisten Web API C#-Beispiele verwendet wird, ist, die abgeleitete Klasse FileConfiguration zu verwenden, um Informationen von ordnungsgemäß erstellten Anwendungskonfigurationsdateien zu lesen, wie in der Darstellung in den folgenden Zeilen veranschaulicht.
FileConfiguration config = new FileConfiguration(null);
Authentication auth = new Authentication(config);
httpClient = new HttpClient(auth.ClientHandler, true);
Weitere Informationen finden Sie im Abschnitt FileConfiguration-Verbindungseinstellungen Obwohl die Authentication-Klasse mehrere öffentliche Eigenschaften und Methoden enthält, werden diese hauptsächlich bereitgestellt, um die Erstellung der ClientHandler-Eigenschaft zu unterstützen. Der Zugriff erfolgt selten direkt über die meisten Clientanwendungen.
Klassenlisten
Den aktuellen Code für diese Klasse finden Sie im CRM SDK Web API Helper Library NuGet-Paket.
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security;
using System.Threading.Tasks;
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
{
private Configuration _config = null;
private HttpMessageHandler _clientHandler = null;
private AuthenticationContext _context = null;
private string _authority = null;
#region Constructors
/// <summary>
/// Base constructor.
/// </summary>
public Authentication() { }
/// <summary>
/// Establishes an authentication session for the service.
/// </summary>
/// <param name="config">A populated configuration object.</param>
public Authentication(Configuration config)
: base()
{
if (config == null)
throw new Exception("Configuration cannot be null.");
_config = config;
SetClientHandler();
}
/// <summary>
/// Custom constructor that allows adding an authority determined asynchronously before
/// instantiating the Authentication class.
/// </summary>
/// <remarks>For a WPF application, first call DiscoverAuthorityAsync(), and then call this
/// constructor passing in the authority value.</remarks>
/// <param name="config">A populated configuration object.</param>
/// <param name="authority">The URL of the authority.</param>
public Authentication(Configuration config, string authority)
: base()
{
if (config == null)
throw new Exception("Configuration cannot be null.");
_config = config;
Authority = authority;
SetClientHandler();
}
#endregion Constructors
#region Properties
/// <summary>
/// The authentication context.
/// </summary>
public AuthenticationContext Context
{
get
{ return _context; }
set
{ _context = value; }
}
/// <summary>
/// The HTTP client message handler.
/// </summary>
public HttpMessageHandler ClientHandler
{
get
{ return _clientHandler; }
set
{ _clientHandler = value; }
}
/// <summary>
/// The URL of the authority to be used for authentication.
/// </summary>
public string Authority
{
get
{
if (_authority == null)
_authority = DiscoverAuthority(_config.ServiceUrl);
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 (_config != null && (!string.IsNullOrEmpty(_config.Username) && _config.Password != null))
{
UserCredential cred = new UserCredential(_config.Username, _config.Password);
return _context.AcquireToken(_config.ServiceUrl, _config.ClientId, cred);
}
return _context.AcquireToken(_config.ServiceUrl, _config.ClientId, new Uri(_config.RedirectUrl),
PromptBehavior.Auto);
}
/// <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 log-on credentials. 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(_config.ServiceUrl, _config.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>
/// <returns>The URL of the authentication authority on the specified endpoint address, or an empty string
/// if the authority cannot be discovered.</returns>
public static string DiscoverAuthority(string serviceUrl)
{
try
{
AuthenticationParameters ap = AuthenticationParameters.CreateFromResourceUrlAsync(
new Uri(serviceUrl + "api/data/")).Result;
return ap.Authority;
}
catch (HttpRequestException e)
{
throw new Exception("An HTTP request exception occurred during authority discovery.", e);
}
catch (System.Exception e )
{
// This exception ocurrs when the service is not configured for OAuth.
if( e.HResult == -2146233088 )
{
return String.Empty;
}
else
{
throw e;
}
}
}
/// <summary>
/// Discover the authentication authority asynchronously.
/// </summary>
/// <param name="serviceUrl">The specified endpoint address</param>
/// <returns>The URL of the authentication authority on the specified endpoint address, or an empty string
/// if the authority cannot be discovered.</returns>
public static async Task<string> DiscoverAuthorityAsync(string serviceUrl)
{
try
{
AuthenticationParameters ap = await AuthenticationParameters.CreateFromResourceUrlAsync(
new Uri(serviceUrl + "api/data/"));
return ap.Authority;
}
catch (HttpRequestException e)
{
throw new Exception("An HTTP request exception occurred during authority discovery.", e);
}
catch (Exception e)
{
// These exceptions ocurr when the service is not configured for OAuth.
// -2147024809 message: Invalid authenticate header format Parameter name: authenticateHeader
if (e.HResult == -2146233088 || e.HResult == -2147024809)
{
return String.Empty;
}
else
{
throw e;
}
}
}
/// <summary>
/// Sets the client message handler as appropriate for the type of authentication
/// in use on the web service endpoint.
/// </summary>
private void SetClientHandler()
{
// Check the Authority to determine if OAuth authentication is used.
if (String.IsNullOrEmpty(Authority))
{
if (_config.Username != String.Empty)
{
_clientHandler = new HttpClientHandler()
{ Credentials = new NetworkCredential(_config.Username, _config.Password, _config.Domain) };
}
else
// No username is provided, so try to use the default domain credentials.
{
_clientHandler = new HttpClientHandler()
{ UseDefaultCredentials = true };
}
}
else
{
_clientHandler = new OAuthMessageHandler(this, new HttpClientHandler());
_context = new AuthenticationContext(Authority, false);
}
}
#endregion Methods
/// <summary>
/// Custom HTTP client handler that adds the Authorization header to message requests. This
/// is required for IFD and Online deployments.
/// </summary>
class OAuthMessageHandler : DelegatingHandler
{
Authentication _auth = null;
public OAuthMessageHandler( Authentication auth, HttpMessageHandler innerHandler )
: base(innerHandler)
{
_auth = auth;
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
// It is a best practice to refresh the access token before every message request is sent. Doing so
// avoids having to check the expiration date/time of the token. This operation is quick.
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _auth.AcquireToken().AccessToken);
return base.SendAsync(request, cancellationToken);
}
}
}
}
Siehe auch
Erste Schritte mit dem Microsoft Dynamics 365 Web API (C#)
Starten eines Dynamics 365-Web-API-Projekts in Visual Studio (C#)
Verwenden Sie die Microsoft Dynamics 365 WEB API Hilfe-Bibliothek (C#)
Web API-Hilfecode: Konfigurationsklassen
Web API-Hilfecode: CrmHttpResponseException-Klasse
Microsoft Dynamics 365
© 2017 Microsoft. Alle Rechte vorbehalten. Copyright