كيفية الاستفادة من الهوية المدارة الخاصة بتطبيق Service Fabric للوصول إلى خدمات Azure

يمكن لتطبيقات Service Fabric الاستفادة من الهويات المدارة للوصول إلى موارد Azure الأخرى التي تدعم المصادقة المستندة إلى Microsoft Azure Active Directory. يمكن للتطبيق الحصول على الرمز المميز للوصول يمثل هويته، والذي قد يكون معين من قبل النظام أو معين من قبل المستخدم، واستخدامه كرمز "للحامل" للمصادقة على نفسه لخدمة أخرى - تعرف أيضا باسم خادم الموارد المحمية. يمثل هذا الرمز المميز الهوية المعينة لتطبيق Service Fabric، وسيتم إصداره فقط إلى موارد Azure (بما في ذلك تطبيقات SF) التي تشترك في هذه الهوية. راجع وثائق نظرة عامة على الهوية المدارة للحصول على وصف مفصل للهويات المدارة، بالإضافة إلى التمييز بين الهويات المعينة من قبل النظام والهويات التي يعينها المستخدم. سنشير إلى تطبيق Service Fabric الذي تم تمكين الهوية المدارة كتطبيق خاص بالعميل في جميع أنحاء هذه المقالة.

راجع نموذج تطبيق مصاحب يوضح استخدام الهويات المدارة لتطبيق Service Fabric المعين من قبل النظام والمعين بواسطة المستخدم مع الخدمات والحاويات الموثوقة.

هام

تمثل الهوية المدارة الاقتران بين مورد Azure وكيان الخدمة في مستأجرMicrosoft Azure Active Directory المقابل المقترن بالاشتراك الذي يحتوي على المورد. يعلى هذا النحو، في سياق Service Fabric، يتم دعم الهويات المدارة فقط للتطبيقات التي يتم توزيعها كموارد Azure.

هام

قبل استخدام الهوية المدارة لتطبيق Service Fabric، يجب منح التطبيق الخاص بالعميل حق الوصول إلى المورد المحمي. يرجى الرجوع إلى قائمة خدمات Azure التي تدعم مصادقة Microsoft Azure Active Directory للتحقق من وجود دعم، ثم إلى وثائق الخدمة المعنية للحصول على خطوات محددة لمنح وصول الهوية إلى الموارد ذات الاهتمام.

الاستفادة من هوية مدارة باستخدام هوية Azure.

يدعم Azure Identity SDK الآن Service Fabric. يؤدي استخدام هوية Azure.إلى جعل كتابة التعليمات البرمجية لاستخدام الهويات المدارة من تطبيق Service Fabric أسهل لأنه يتعامل مع إحضار الرموز المميزة والرموز المميزة للتخزين المؤقت ومصادقة الخادم. أثناء الوصول إلى معظم الموارد الخاصة بـ Azure، يتم إخفاء مفهوم الرمز المميز.

يتوفرService Fabric دعم بالإصدارات التالية لهذه اللغات:

العينة C# لتهيئة بيانات الاعتماد واستخدام بيانات الاعتماد لإحضار السر من Azure Key Vault:

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;

namespace MyMIService
{
    internal sealed class MyMIService : StatelessService
    {
        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            try
            {
                // Load the service fabric application managed identity assigned to the service
                ManagedIdentityCredential creds = new ManagedIdentityCredential();

                // Create a client to keyvault using that identity
                SecretClient client = new SecretClient(new Uri("https://mykv.vault.azure.net/"), creds);

                // Fetch a secret
                KeyVaultSecret secret = (await client.GetSecretAsync("mysecret", cancellationToken: cancellationToken)).Value;
            }
            catch (CredentialUnavailableException e)
            {
                // Handle errors with loading the Managed Identity
            }
            catch (RequestFailedException)
            {
                // Handle errors with fetching the secret
            }
            catch (Exception e)
            {
                // Handle generic errors
            }
        }
    }
}

الحصول على رمز الوصول المميز باستخدام واجهة برمجة تطبيقات REST

في نظام المجموعات الممكنة للهوية المدارة، يعرض وقت تشغيل Service Fabric نقطة نهاية مضيف محلي يمكن للتطبيقات استخدامها للحصول على رموز الوصول المميز. تتوفر نقطة النهاية في كل عقدة من نظام المجموعة، ويمكن الوصول إليها من قبل جميع الكيانات الموجودة على تلك العقدة. يمكن للمتصلين المصرح لهم الحصول على الرمز المميز للوصول عن طريق الاتصال بنقطة النهاية هذه وتقديم رمز مصادقة ؛ يتم إنشاء التعليمة البرمجية بواسطة وقت تشغيل Service Fabric لكل تنشيط حزمة رمز خدمة متميز، وهي مرتبطة بعمر العملية التي تستضيف حزمة التعليمات البرمجية للخدمة هذه.

وعلى وجه التحديد، سيتم إدراج بيئة خدمة Service Fabric التي تدعم الهوية المدارة بالمتغيرات التالية:

  • 'IDENTITY_ENDPOINT': نقطة النهاية للمضيف المحلي المطابقة للهوية المدارة للخدمة
  • "IDENTITY_HEADER": تعليمة برمجية مصادقة فريدة تمثل الخدمة على العقدة الحالية
  • 'IDENTITY_SERVER_THUMBPRINT': بصمة إبهام الخاصة بخادم الهوية المدار بواسطة Service Fabric

هام

يجب أن تأخذ تعليمة برمجية التطبيق في الاعتبار قيمة متغير البيئة "IDENTITY_HEADER" كبيانات حساسة - يجب عدم تسجيلها أو نشرها بطريقة أخرى. ليس لتعليمة برمجية المصادقة أي قيمة خارج العقدة المحلية، أو بعد انتهاء العملية التي تستضيف الخدمة، ولكنها تمثل هوية خدمة Service Fabric، وبالتالي يجب معاملته بنفس الاحتياطات مثل الرمز المميز للوصول نفسه.

للحصول على الرمز المميز، يقوم العميل بتنفيذ الخطوات التالية:

  • يشكل عنوان URI عن طريق تسلسل نقطة النهاية الخاصة بالهوية المدارة (القيمة IDENTITY_ENDPOINT) مع إصدار واجهة برمجة التطبيقات والمورد (الجمهور) المطلوب للرمز المميز
  • إنشاء طلب GET http(s) لعنوان URI المحدد
  • إضافة منطق التحقق من الشهادة الخاصة بصحة الخادم المناسب
  • إضافة تعليمة برمجية المصادقة (قيمة IDENTITY_HEADER) كعنوان إلى الطلب
  • إرسال الطلب

ستحتوي الاستجابة الناجحة على حمولة JSON تمثل الرمز المميز للوصول الناتج، بالإضافة إلى بيانات التعريف التي تصفها. كما سيتضمن الرد الفاشل شرحا للفشل. انظر أدناه للحصول على معلومات إضافية حول معالجة الأخطاء.

سيتم تخزين الرمز المميز للوصول مؤقتا بواسطة Service Fabric على مستويات مختلفة (عقدة، نظام المجموعة، خدمة مزود الموارد)، لذلك لا تعني الاستجابة الناجحة بالضرورة أن الرمز المميز قد تم إصداره مباشرة استجابة لطلب تطبيق المستخدم. سيتم تخزين الرموز المميزة مؤقتا لمدة تقل عن عمرها الافتراضي، وبالتالي يضمن التطبيق تلقي الرمز المميز الصالح. يوصى بأن يقوم تعليمة برمجية التطبيق بتخزين نفسها مؤقتا لأي رموز مميزة للوصول يكتسبها. يجب أن يتضمن مفتاح التخزين المؤقت (اشتقاقا) الجمهور.

طلب العينة:

GET 'https://localhost:2377/metadata/identity/oauth2/token?api-version=2019-07-01-preview&resource=https://vault.azure.net/' HTTP/1.1 Secret: 912e4af7-77ba-4fa5-a737-56c8e3ace132

الموقع:

العنصر الوصف
GET HTTP-Verb، يشير إلى أنك تريد استرداد البيانات من نقطة النهاية. في هذه الحالة، رمز دخول OAuth المميز.
https://localhost:2377/metadata/identity/oauth2/token نقطة النهاية الخاصة بالهوية المدارة لتطبيقات Service Fabric، التي يتم توفيرها عبر متغير بيئة IDENTITY_ENDPOINT.
api-version معلمة سلسلة استعلام، تحدد إصدار واجهة برمجة التطبيقات لخدمة الرمز المميز للهوية المدارة؛ حاليا القيمة الوحيدة المقبولة هي 2019-07-01-preview، وهي عرضة للتغيير.
resource معلمة سلسلة الاستعلام، تشير إلى معرف التطبيق معرف URI للمورد الهدف. وسينعكس ذلك على aud المطالبة (الجمهور) بالرمز المميز الصادر. يحتاج هذا المثال رمزا مميزا للوصول إلى Azure Key Vault، الذي يكون عنوان URI الخاص بمعرف التطبيق الخاص بهhttps://vault.azure.net/.
Secret حقل عنوان طلب HTTP، مطلوب بواسطة خدمة الرمز المميز للوصول للهوية المدارة من قبل Service Fabric لخدمات Service Fabric لمصادقة المتصل. يتم توفير هذه القيمة بواسطة وقت تشغيل SF عبر المتغير الخاص ببيئة IDENTITY_HEADER.

استجابة العينة:

HTTP/1.1 200 OK
Content-Type: application/json
{
    "token_type":  "Bearer",
    "access_token":  "eyJ0eXAiO...",
    "expires_on":  1565244611,
    "resource":  "https://vault.azure.net/"
}

الموقع:

العنصر الوصف
token_type نوع الرمز المميز؛ في هذه الحالة، رمز المميز للوصول "للحامل"، مما يعني أن مقدم العرض ("الحامل") لهذا الرمز المميز هو الموضوع المقصود للرمز المميز.
access_token رمز الوصول المميز المطلوب. عند استدعاء واجهة برمجة تطبيقات REST المؤمنة، يتم تضمين الرمز المميز في حقل عنوان طلب Authorization كرمز مميز "للحامل"، مما يسمح لواجهة برمجة التطبيقات بمصادقة المتصل.
expires_on الطابع الزمني لانتهاء صلاحية الرمز المميز للوصول؛ يتم تمثيلها على أنها عدد الثواني من "1970-01-01T0:0:0Z UTC" وتتوافق مع مطالبة الرمز المميز exp. في تلك الحالة، تنتهي صلاحية الرمز المميز في 2019-08-08T06:10:11+00:00 (في RFC 3339)
resource المورد الذي تم إصدار رمز الوصول المميز له، المحدد عبر المعلمة الخاصة بسلسلة الاستعلام resource للطلب؛ يتوافق مع مطالبة الرمز المميز "aud".

الحصول على رمز الوصول المميز باستخدام C #

ما ورد أعلاه يصبح، في C#‎:

namespace Azure.ServiceFabric.ManagedIdentity.Samples
{
    using System;
    using System.Net.Http;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web;
    using Newtonsoft.Json;

    /// <summary>
    /// Type representing the response of the SF Managed Identity endpoint for token acquisition requests.
    /// </summary>
    [JsonObject]
    public sealed class ManagedIdentityTokenResponse
    {
        [JsonProperty(Required = Required.Always, PropertyName = "token_type")]
        public string TokenType { get; set; }

        [JsonProperty(Required = Required.Always, PropertyName = "access_token")]
        public string AccessToken { get; set; }

        [JsonProperty(PropertyName = "expires_on")]
        public string ExpiresOn { get; set; }

        [JsonProperty(PropertyName = "resource")]
        public string Resource { get; set; }
    }

    /// <summary>
    /// Sample class demonstrating access token acquisition using Managed Identity.
    /// </summary>
    public sealed class AccessTokenAcquirer
    {
        /// <summary>
        /// Acquire an access token.
        /// </summary>
        /// <returns>Access token</returns>
        public static async Task<string> AcquireAccessTokenAsync()
        {
            var managedIdentityEndpoint = Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT");
            var managedIdentityAuthenticationCode = Environment.GetEnvironmentVariable("IDENTITY_HEADER");
            var managedIdentityServerThumbprint = Environment.GetEnvironmentVariable("IDENTITY_SERVER_THUMBPRINT");
            // Latest api version, 2019-07-01-preview is still supported.
            var managedIdentityApiVersion = Environment.GetEnvironmentVariable("IDENTITY_API_VERSION");
            var managedIdentityAuthenticationHeader = "secret";
            var resource = "https://management.azure.com/";

            var requestUri = $"{managedIdentityEndpoint}?api-version={managedIdentityApiVersion}&resource={HttpUtility.UrlEncode(resource)}";

            var requestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri);
            requestMessage.Headers.Add(managedIdentityAuthenticationHeader, managedIdentityAuthenticationCode);
            
            var handler = new HttpClientHandler();
            handler.ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, certChain, policyErrors) =>
            {
                // Do any additional validation here
                if (policyErrors == SslPolicyErrors.None)
                {
                    return true;
                }
                return 0 == string.Compare(cert.GetCertHashString(), managedIdentityServerThumbprint, StringComparison.OrdinalIgnoreCase);
            };

            try
            {
                var response = await new HttpClient(handler).SendAsync(requestMessage)
                    .ConfigureAwait(false);

                response.EnsureSuccessStatusCode();

                var tokenResponseString = await response.Content.ReadAsStringAsync()
                    .ConfigureAwait(false);

                var tokenResponseObject = JsonConvert.DeserializeObject<ManagedIdentityTokenResponse>(tokenResponseString);

                return tokenResponseObject.AccessToken;
            }
            catch (Exception ex)
            {
                string errorText = String.Format("{0} \n\n{1}", ex.Message, ex.InnerException != null ? ex.InnerException.Message : "Acquire token failed");

                Console.WriteLine(errorText);
            }

            return String.Empty;
        }
    } // class AccessTokenAcquirer
} // namespace Azure.ServiceFabric.ManagedIdentity.Samples

الوصول إلى مفتاح الاختصار Vault من تطبيق Service Fabric باستخدام الهوية المدارة

تعتمد هذه العينة على ما سبق لإثبات الوصول إلى سر مخزن في Key Vault باستخدام الهوية المدارة.

        /// <summary>
        /// Probe the specified secret, displaying metadata on success.  
        /// </summary>
        /// <param name="vault">vault name</param>
        /// <param name="secret">secret name</param>
        /// <param name="version">secret version id</param>
        /// <returns></returns>
        public async Task<string> ProbeSecretAsync(string vault, string secret, string version)
        {
            // initialize a KeyVault client with a managed identity-based authentication callback
            var kvClient = new Microsoft.Azure.KeyVault.KeyVaultClient(new Microsoft.Azure.KeyVault.KeyVaultClient.AuthenticationCallback((a, r, s) => { return AuthenticationCallbackAsync(a, r, s); }));

            Log(LogLevel.Info, $"\nRunning with configuration: \n\tobserved vault: {config.VaultName}\n\tobserved secret: {config.SecretName}\n\tMI endpoint: {config.ManagedIdentityEndpoint}\n\tMI auth code: {config.ManagedIdentityAuthenticationCode}\n\tMI auth header: {config.ManagedIdentityAuthenticationHeader}");
            string response = String.Empty;

            Log(LogLevel.Info, "\n== {DateTime.UtcNow.ToString()}: Probing secret...");
            try
            {
                var secretResponse = await kvClient.GetSecretWithHttpMessagesAsync(vault, secret, version)
                    .ConfigureAwait(false);

                if (secretResponse.Response.IsSuccessStatusCode)
                {
                    // use the secret: secretValue.Body.Value;
                    response = String.Format($"Successfully probed secret '{secret}' in vault '{vault}': {PrintSecretBundleMetadata(secretResponse.Body)}");
                }
                else
                {
                    response = String.Format($"Non-critical error encountered retrieving secret '{secret}' in vault '{vault}': {secretResponse.Response.ReasonPhrase} ({secretResponse.Response.StatusCode})");
                }
            }
            catch (Microsoft.Rest.ValidationException ve)
            {
                response = String.Format($"encountered REST validation exception 0x{ve.HResult.ToString("X")} trying to access '{secret}' in vault '{vault}' from {ve.Source}: {ve.Message}");
            }
            catch (KeyVaultErrorException kvee)
            {
                response = String.Format($"encountered KeyVault exception 0x{kvee.HResult.ToString("X")} trying to access '{secret}' in vault '{vault}': {kvee.Response.ReasonPhrase} ({kvee.Response.StatusCode})");
            }
            catch (Exception ex)
            {
                // handle generic errors here
                response = String.Format($"encountered exception 0x{ex.HResult.ToString("X")} trying to access '{secret}' in vault '{vault}': {ex.Message}");
            }

            Log(LogLevel.Info, response);

            return response;
        }

        /// <summary>
        /// KV authentication callback, using the application's managed identity.
        /// </summary>
        /// <param name="authority">The expected issuer of the access token, from the KV authorization challenge.</param>
        /// <param name="resource">The expected audience of the access token, from the KV authorization challenge.</param>
        /// <param name="scope">The expected scope of the access token; not currently used.</param>
        /// <returns>Access token</returns>
        public async Task<string> AuthenticationCallbackAsync(string authority, string resource, string scope)
        {
            Log(LogLevel.Verbose, $"authentication callback invoked with: auth: {authority}, resource: {resource}, scope: {scope}");
            var encodedResource = HttpUtility.UrlEncode(resource);

            // This sample does not illustrate the caching of the access token, which the user application is expected to do.
            // For a given service, the caching key should be the (encoded) resource uri. The token should be cached for a period
            // of time at most equal to its remaining validity. The 'expires_on' field of the token response object represents
            // the number of seconds from Unix time when the token will expire. You may cache the token if it will be valid for at
            // least another short interval (1-10s). If its expiration will occur shortly, don't cache but still return it to the 
            // caller. The MI endpoint will not return an expired token.
            // Sample caching code:
            //
            // ManagedIdentityTokenResponse tokenResponse;
            // if (responseCache.TryGetCachedItem(encodedResource, out tokenResponse))
            // {
            //     Log(LogLevel.Verbose, $"cache hit for key '{encodedResource}'");
            //
            //     return tokenResponse.AccessToken;
            // }
            //
            // Log(LogLevel.Verbose, $"cache miss for key '{encodedResource}'");
            //
            // where the response cache is left as an exercise for the reader. MemoryCache is a good option, albeit not yet available on .net core.

            var requestUri = $"{config.ManagedIdentityEndpoint}?api-version={config.ManagedIdentityApiVersion}&resource={encodedResource}";
            Log(LogLevel.Verbose, $"request uri: {requestUri}");

            var requestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri);
            requestMessage.Headers.Add(config.ManagedIdentityAuthenticationHeader, config.ManagedIdentityAuthenticationCode);
            Log(LogLevel.Verbose, $"added header '{config.ManagedIdentityAuthenticationHeader}': '{config.ManagedIdentityAuthenticationCode}'");

            var response = await httpClient.SendAsync(requestMessage)
                .ConfigureAwait(false);
            Log(LogLevel.Verbose, $"response status: success: {response.IsSuccessStatusCode}, status: {response.StatusCode}");

            response.EnsureSuccessStatusCode();

            var tokenResponseString = await response.Content.ReadAsStringAsync()
                .ConfigureAwait(false);

            var tokenResponse = JsonConvert.DeserializeObject<ManagedIdentityTokenResponse>(tokenResponseString);
            Log(LogLevel.Verbose, "deserialized token response; returning access code..");

            // Sample caching code (continuation):
            // var expiration = DateTimeOffset.FromUnixTimeSeconds(Int32.Parse(tokenResponse.ExpiresOn));
            // if (expiration > DateTimeOffset.UtcNow.AddSeconds(5.0))
            //    responseCache.AddOrUpdate(encodedResource, tokenResponse, expiration);

            return tokenResponse.AccessToken;
        }

        private string PrintSecretBundleMetadata(SecretBundle bundle)
        {
            StringBuilder strBuilder = new StringBuilder();

            strBuilder.AppendFormat($"\n\tid: {bundle.Id}\n");
            strBuilder.AppendFormat($"\tcontent type: {bundle.ContentType}\n");
            strBuilder.AppendFormat($"\tmanaged: {bundle.Managed}\n");
            strBuilder.AppendFormat($"\tattributes:\n");
            strBuilder.AppendFormat($"\t\tenabled: {bundle.Attributes.Enabled}\n");
            strBuilder.AppendFormat($"\t\tnbf: {bundle.Attributes.NotBefore}\n");
            strBuilder.AppendFormat($"\t\texp: {bundle.Attributes.Expires}\n");
            strBuilder.AppendFormat($"\t\tcreated: {bundle.Attributes.Created}\n");
            strBuilder.AppendFormat($"\t\tupdated: {bundle.Attributes.Updated}\n");
            strBuilder.AppendFormat($"\t\trecoveryLevel: {bundle.Attributes.RecoveryLevel}\n");

            return strBuilder.ToString();
        }

        private enum LogLevel
        {
            Info,
            Verbose
        };

        private void Log(LogLevel level, string message)
        {
            if (level != LogLevel.Verbose
                || config.DoVerboseLogging)
            {
                Console.WriteLine(message);
            }
        }

معالجة الأخطاء

يشير الحقل 'رمز الحالة' لعنوان استجابة HTTP إلى حالة نجاح الطلب؛ تشير حالة '200 OK' إلى النجاح، وستتضمن الاستجابة رمز الوصول المميز كما هو موضح أعلاه. فيما يلي قائمة تعداد قصيرة لاستجابات الأخطاء المحتملة.

التعليمة البرمجية للحالة سبب الخطأ كيفية التعامل
404 لم يتم العثور. تعليمة برمجية المصادقة غير معروفة، أو لم يتم تعيين هوية مدارة للتطبيق. تصحيح إعداد التطبيق أو تعليمة برمجية الحصول على الرمز المميز.
429 طلبات كثيرة جدًا. تم الوصول إلى حد التقييد، مفروض من قبل AAD (دليل Azure النشط) أو SF. أعد المحاولة باستخدام التراجع الأسي. انظر التوجيه أدناه.
4xx خطأ في الطلب. معلمة واحدة أو أكثر من معلمات الطلب غير صحيحة. لا تحاول. افحص تفاصيل الخطأ للحصول على مزيد من المعلومات. أخطاء 4xx هي أخطاء وقت التصميم.
5xx يوجد خطأ في الخدمة. أرجع النظام الفرعي للهوية المدارة أوMicrosoft Azure Active Directory خطأ ما. فمن الآمن لإعادة المحاولة بعد فترة قصيرة. قد تصطدم بحالة تقييد (429) عند إعادة المحاولة.

إذا حدث خطأ، فإن النص النصي المناسب للاستجابة في HTTP يحتوي على عنصر JSON مع تفاصيل الخطأ:

العنصر الوصف
الرمز الرمز الخاص بالخطأ
correlationId معرف الارتباط الذي يمكن استخدامه لتصحيح الأخطاء.
رسالة وصف مطول للخطأ. يمكن تغيير أوصاف الخطأ في أي وقت. لا تعتمد على نفس رسالة الخطأ.

خطأ في العينة:

{"error":{"correlationId":"7f30f4d3-0f3a-41e0-a417-527f21b3848f","code":"SecretHeaderNotFound","message":"Secret is not found in the request headers."}}

فيما يلي قائمة بأخطاء Service Fabric النموذجية المحددة بالهويات المدارة:

رمز رسالة الوصف
SecretHeaderNotFound لم يتم العثور على بيانات سرية في عنواين الطلبات. ولم يتم تزويد تعليمة برمجية المصادقة مع الطلب.
ManagedIdentityNotFound لم يتم العثور على الهوية المدارة الخاصة بمضيف التطبيق المحدد. لا يحتوي التطبيق على هوية، أو تعليمة برمجية المصادقة غير معروفة.
ArgumentNullOrEmpty يجب ألا تكون المعلمة "المورد" خالية أو فارغة السلسلة. المورد غير متوفر(الجمهور) في الطلب.
InvalidApiVersion إصدار api '' غير مدعوم الإصدار المدعوم هو "2019-07-01-إصدار أولي". إصدار API المفقود أو غير المدعوم المحدد في عنوان URI للطلب.
InternalServerError حدث خطأ. تمت مصادفة خطأ في النظام الفرعي للهوية المدارة، ربما خارج المكدس الخاص بـ Service Fabric. السبب الأكثر احتمالا هو قيمة غير صحيحة محددة للمورد (تحقق لاحق '/'؟)

توجيه إعادة المحاولة

في الأغلب ما يكون رمز الخطأ الوحيد القابل لإعادة المحاولة هو 429 (طلبات كثيرة جدا) ؛ قد تكون أخطاء الخادم الداخلية / رموز خطأ 5xx قابلة لإعادة المحاولة، على الرغم من أن السبب قد يكون دائما.

تنطبق حدود التقييد على عدد المكالمات التي يتم إجراؤها على النظام الفرعي للهوية المدارة - وتحديدا تبعيات "المنبع" (خدمة Azure للهوية المدارة، أو خدمة الرمز المميز الآمن). يقوم Service Fabric بتخزين الرموز المميزة مؤقتا على مستويات مختلفة في البنية الأساسية لبرنامج ربط العمليات التجارية، ولكن نظرا للطبيعة الموزعة للمكونات المعنية، قد يواجه المتصل استجابات تقييد غير متناسقة (أي يتم تقيدها على عقدة / مثيل واحد من التطبيق، ولكن ليس على عقدة مختلفة أثناء طلب رمز مميز لنفس الهوية.) عند تعيين شرط التقييد، قد تفشل الطلبات اللاحقة من نفس التطبيق مع رمز حالة HTTP 429 (طلبات كثيرة جدا) حتى يتم مسح الشرط.

يوصى بإعادة محاولة الطلبات التي فشلت بسبب التقييد مع التراجع الأسي، على النحو التالي:

فهرس المكالمات الإجراء المتعلق بتلقي 429
1 انتظر ثانية واحدة ثم أعد المحاولة
2 انتظر ثانيتين ثم أعد المحاولة
3 انتظر 4 ثوان ثم أعد المحاولة
4 انتظر 8 ثوان ثم أعد المحاولة
4 انتظر 8 ثوان ثم أعد المحاولة
5 انتظر 16 ثانية ثم أعد المحاولة

معرفات الموارد لخدمات Azure

راجع خدمات Azure التي تدعم مصادقةMicrosoft Azure Active Directory للحصول على قائمة بالموارد التي تدعم Microsoft Azure Active Directory وتم اختبارها باستخدام الهويات المُدارة لموارد Azure ومعرفات الموارد الخاصة بها.

الخطوات التالية