Aracılığıyla paylaş


Dayanıklı İşlevler'de insan etkileşimi - Telefon doğrulama örneği

Bu örnek, insan etkileşimi içeren bir Dayanıklı İşlevler düzenlemenin nasıl derlendiğini gösterir. Gerçek bir kişi otomatik bir işleme dahil olduğunda, işlemin kişiye bildirim gönderebilmesi ve zaman uyumsuz olarak yanıt alabilmesi gerekir. Ayrıca kişinin kullanılamama olasılığına da izin vermelidir. (Bu son bölüm, zaman aşımlarının önemli hale geldiği bölümdür.)

Bu örnek, SMS tabanlı bir telefon doğrulama sistemi uygular. Bu tür akışlar genellikle müşterinin telefon numarasını doğrularken veya çok faktörlü kimlik doğrulaması (MFA) için kullanılır. Uygulamanın tamamı birkaç küçük işlev kullanılarak yapıldığından bu güçlü bir örnektir. Veritabanı gibi dış veri deposu gerekmez.

Not

Azure İşlevleri için Node.js programlama modelinin 4. sürümü genel olarak kullanılabilir. Yeni v4 modeli, JavaScript ve TypeScript geliştiricileri için daha esnek ve sezgisel bir deneyime sahip olacak şekilde tasarlanmıştır. Geçiş kılavuzunda v3 ve v4 arasındaki farklar hakkında daha fazla bilgi edinin.

Aşağıdaki kod parçacıklarında JavaScript (PM4), yeni deneyim olan programlama modeli V4'i belirtir.

Önkoşullar

Senaryoya genel bakış

Telefon doğrulaması, uygulamanızın son kullanıcılarının spam gönderen olmadığını ve söyledikleri kişi olduklarını doğrulamak için kullanılır. Çok faktörlü kimlik doğrulaması, kullanıcı hesaplarını korsanlardan korumaya yönelik yaygın bir kullanım örneğidir. Kendi telefon doğrulamanızı uygulamanın zorluğu, bir insanla durum bilgisi olan bir etkileşime ihtiyaç duymasıdır. Son kullanıcıya genellikle bir kod (örneğin, 4 basamaklı bir sayı) sağlanır ve makul bir süre içinde yanıt vermesi gerekir.

Sıradan Azure İşlevleri durum bilgisi yoktur (diğer platformlardaki diğer birçok bulut uç noktası gibi), bu tür etkileşimler bir veritabanında veya başka bir kalıcı depoda durumu açıkça yönetmeyi içerir. Ayrıca, etkileşimin birlikte koordine edilebilen birden çok işleve bölünmesi gerekir. Örneğin, bir koda karar vermek, bir yerde kalıcı hale getirmek ve kullanıcının telefonuna göndermek için en az bir işleve ihtiyacınız vardır. Ayrıca, kullanıcıdan yanıt almak ve kod doğrulamasını yapmak için bir şekilde özgün işlev çağrısıyla eşlemek için en az bir işleve daha ihtiyacınız vardır. Zaman aşımı, güvenliği sağlamak için de önemli bir unsurdur. Oldukça hızlı bir şekilde karmaşık olabilir.

Dayanıklı İşlevler kullandığınızda bu senaryonun karmaşıklığı büyük ölçüde azalır. Bu örnekte göreceğiniz gibi, bir orchestrator işlevi durum bilgisi olan etkileşimi dış veri depolarını içermeden kolayca yönetebilir. Orchestrator işlevleri dayanıklı olduğundan, bu etkileşimli akışlar da son derece güvenilirdir.

Twilio tümleştirmesini yapılandırma

Bu örnek, cep telefonuna SMS mesajları göndermek için Twilio hizmetini kullanmayı içerir. Azure İşlevleri zaten Twilio için destekTwilio bağlaması ve örnek bu özelliği kullanır.

İhtiyacınız olan ilk şey bir Twilio hesabıdır. adresinde https://www.twilio.com/try-twilioücretsiz bir tane oluşturabilirsiniz. Hesabınız olduktan sonra aşağıdaki üç uygulama ayarlarını işlev uygulamanıza ekleyin.

Uygulama ayarı adı Değer, açıklama
TwilioAccountSid Twilio hesabınızın SID değeri
TwilioAuthToken Twilio hesabınız için Kimlik Doğrulama belirteci
TwilioPhoneNumber Twilio hesabınızla ilişkili telefon numarası. Bu, SMS iletileri göndermek için kullanılır.

İşlevler

Bu makalede, örnek uygulamadaki aşağıdaki işlevlerde yol gösterilir:

Not

HttpStart Örnek uygulamadaki ve hızlı başlangıçtaki işlev orchestrator işlevini tetikleyen Orchestration istemcisi işlevi görür.

E4_SmsPhoneVerification orchestrator işlevi

[FunctionName("E4_SmsPhoneVerification")]
public static async Task<bool> Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    string phoneNumber = context.GetInput<string>();
    if (string.IsNullOrEmpty(phoneNumber))
    {
        throw new ArgumentNullException(
            nameof(phoneNumber),
            "A phone number input is required.");
    }

    int challengeCode = await context.CallActivityAsync<int>(
        "E4_SendSmsChallenge",
        phoneNumber);

    using (var timeoutCts = new CancellationTokenSource())
    {
        // The user has 90 seconds to respond with the code they received in the SMS message.
        DateTime expiration = context.CurrentUtcDateTime.AddSeconds(90);
        Task timeoutTask = context.CreateTimer(expiration, timeoutCts.Token);

        bool authorized = false;
        for (int retryCount = 0; retryCount <= 3; retryCount++)
        {
            Task<int> challengeResponseTask =
                context.WaitForExternalEvent<int>("SmsChallengeResponse");

            Task winner = await Task.WhenAny(challengeResponseTask, timeoutTask);
            if (winner == challengeResponseTask)
            {
                // We got back a response! Compare it to the challenge code.
                if (challengeResponseTask.Result == challengeCode)
                {
                    authorized = true;
                    break;
                }
            }
            else
            {
                // Timeout expired
                break;
            }
        }

        if (!timeoutTask.IsCompleted)
        {
            // All pending timers must be complete or canceled before the function exits.
            timeoutCts.Cancel();
        }

        return authorized;
    }
}

Not

İlk başta belirgin olmayabilir, ancak bu düzenleyici belirleyici düzenleme kısıtlamasını ihlal etmez. Bu belirleyicidir çünkü CurrentUtcDateTime özelliği zamanlayıcı süre sonu süresini hesaplamak için kullanılır ve orchestrator kodunda bu noktadaki her yeniden yürütmede aynı değeri döndürür. Bu davranış, her yinelenen çağrısından aynı winner sonuçların elde edilmesini sağlamak için Task.WhenAnyönemlidir.

Bu düzenleyici işlevi başlatıldıktan sonra aşağıdakileri yapar:

  1. SMS bildirimini göndereceği bir telefon numarası alır.
  2. Kullanıcıya SMS iletisi göndermek için E4_SendSmsChallenge çağırır ve beklenen 4 basamaklı sınama kodunu geri döndürür.
  3. Geçerli saatten 90 saniye sonra tetikleyen dayanıklı bir zamanlayıcı oluşturur.
  4. Zamanlayıcıya paralel olarak, kullanıcıdan gelen bir SmsChallengeResponse olayını bekler.

Kullanıcı dört basamaklı kod içeren bir SMS iletisi alır. Doğrulama işlemini tamamlamak için aynı dört basamaklı kodu orchestrator işlev örneğine göndermek için 90 saniyeleri vardır. Yanlış kodu gönderirlerse, doğru kodu almak için ek üç deneme alır (aynı 90 saniyelik pencerede).

Uyarı

Bir sınama yanıtı kabul edildiğinde yukarıdaki örnekte olduğu gibi süreölçerlerin süresinin dolması gerekmiyorsa zamanlayıcıları iptal etmek önemlidir.

etkinlik işlevini E4_SendSmsChallenge

E4_SendSmsChallenge işlevi, dört basamaklı kodu içeren SMS iletisini son kullanıcıya göndermek için Twilio bağlamasını kullanır.

[FunctionName("E4_SendSmsChallenge")]
public static int SendSmsChallenge(
    [ActivityTrigger] string phoneNumber,
    ILogger log,
    [TwilioSms(AccountSidSetting = "TwilioAccountSid", AuthTokenSetting = "TwilioAuthToken", From = "%TwilioPhoneNumber%")]
        out CreateMessageOptions message)
{
    // Get a random number generator with a random seed (not time-based)
    var rand = new Random(Guid.NewGuid().GetHashCode());
    int challengeCode = rand.Next(10000);

    log.LogInformation($"Sending verification code {challengeCode} to {phoneNumber}.");

    message = new CreateMessageOptions(new PhoneNumber(phoneNumber));
    message.Body = $"Your verification code is {challengeCode:0000}";

    return challengeCode;
}

Not

Örnek kodu çalıştırmak için önce İşlevler için Nuget paketini yüklemeniz Microsoft.Azure.WebJobs.Extensions.Twilio gerekir. Ana Twilio nuget paketini de yüklemeyin çünkü bu, derleme hatalarıyla sonuçlanır sürüm oluşturma sorunlarına neden olabilir.

Örneği çalıştırma

Örnekteki HTTP ile tetiklenen işlevleri kullanarak, aşağıdaki HTTP POST isteğini göndererek düzenlemeyi başlatabilirsiniz:

POST http://{host}/orchestrators/E4_SmsPhoneVerification
Content-Length: 14
Content-Type: application/json

"+1425XXXXXXX"
HTTP/1.1 202 Accepted
Content-Length: 695
Content-Type: application/json; charset=utf-8
Location: http://{host}/runtime/webhooks/durabletask/instances/741c65651d4c40cea29acdd5bb47baf1?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}

{"id":"741c65651d4c40cea29acdd5bb47baf1","statusQueryGetUri":"http://{host}/runtime/webhooks/durabletask/instances/741c65651d4c40cea29acdd5bb47baf1?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}","sendEventPostUri":"http://{host}/runtime/webhooks/durabletask/instances/741c65651d4c40cea29acdd5bb47baf1/raiseEvent/{eventName}?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}","terminatePostUri":"http://{host}/runtime/webhooks/durabletask/instances/741c65651d4c40cea29acdd5bb47baf1/terminate?reason={text}&taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}"}

Orchestrator işlevi sağlanan telefon numarasını alır ve rastgele oluşturulan 4 basamaklı doğrulama koduyla (örneğin, 2168) hemen bir SMS iletisi gönderir. İşlev daha sonra yanıt için 90 saniye bekler.

Kodu yanıtlamak için başka bir işlevin içinde (.NET) veya raiseEvent (JavaScript/TypeScript) kullanabilir RaiseEventAsync veya yukarıdaki 202 yanıtında başvurulan sendEventPostUri HTTP POST web kancasını çağırabilir ve değerini olayın SmsChallengeResponseadıyla değiştirebilirsiniz{eventName}:

POST http://{host}/runtime/webhooks/durabletask/instances/741c65651d4c40cea29acdd5bb47baf1/raiseEvent/SmsChallengeResponse?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}
Content-Length: 4
Content-Type: application/json

2168

Zamanlayıcının süresi dolmadan önce bunu gönderirseniz, düzenleme tamamlanır ve alan olarak ayarlanır trueve output başarılı bir doğrulama olduğunu gösterir.

GET http://{host}/runtime/webhooks/durabletask/instances/741c65651d4c40cea29acdd5bb47baf1?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}
HTTP/1.1 200 OK
Content-Length: 144
Content-Type: application/json; charset=utf-8

{"runtimeStatus":"Completed","input":"+1425XXXXXXX","output":true,"createdTime":"2017-06-29T19:10:49Z","lastUpdatedTime":"2017-06-29T19:12:23Z"}

Zamanlayıcının süresinin dolmasına izin verirseniz veya dört kez yanlış kod girerseniz, durumu sorgulayabilir ve telefon doğrulamasının başarısız olduğunu belirten bir false düzenleme işlevi çıkışı görebilirsiniz.

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 145

{"runtimeStatus":"Completed","input":"+1425XXXXXXX","output":false,"createdTime":"2017-06-29T19:20:49Z","lastUpdatedTime":"2017-06-29T19:22:23Z"}

Sonraki adımlar

Bu örnek, özellikle WaitForExternalEvent de CreateTimer API'ler gibi Dayanıklı İşlevler gelişmiş özelliklerinden bazılarını göstermiştir. Bunların güvenilir bir zaman aşımı sistemi uygulamak için (C#)/context.df.Task.any (JavaScript/TypeScript)/context.task_any (Python) ile Task.WaitAny nasıl birleştirilebileceğini gördünüz. Bu sistem genellikle gerçek kişilerle etkileşimde bulunur. Belirli konuların ayrıntılı kapsamını sunan bir dizi makale okuyarak Dayanıklı İşlevler kullanma hakkında daha fazla bilgi edinebilirsiniz.