Invio di notifiche push sicure con Hub di notifica di Azure

Overview

Importante

Per completare l'esercitazione, è necessario disporre di un account Azure attivo. Se non si dispone di un account, è possibile creare un account di valutazione gratuita in pochi minuti. Per informazioni dettagliate, vedere la pagina relativa alla versione di valutazione gratuita di Azure.

Il supporto per le notifiche push in Microsoft Azure consente di accedere a un'infrastruttura di messaggistica push di facile utilizzo, multipiattaforma con scalabilità orizzontale, che semplifica considerevolmente l'implementazione delle notifiche push sia per le applicazioni consumer sia per quelle aziendali per piattaforme mobili.

A causa di vincoli normativi o di sicurezza, un'applicazione potrebbe talvolta includere nella notifica informazioni che non è possibile trasmettere attraverso l'infrastruttura di notifiche push standard. Questa esercitazione descrive come conseguire la stessa esperienza inviando informazioni sensibili attraverso una connessione autenticata e sicura tra il dispositivo client Android e il back-end dell'app.

A livello generale, il flusso è il seguente:

  1. Il back-end dell'app:
    • Archivia il payload sicuro nel database back-end.
    • Invia l'ID di questa notifica al dispositivo Android (non vengono inviate informazioni sicure).
  2. L'app sul dispositivo, quando riceve la notifica:
    • Il dispositivo Android contatta il back-end richiedendo il payload sicuro.
    • L'app può indicare il payload come una notifica sul dispositivo.

È importante notare che nel flusso precedente e in questa esercitazione si presuppone che il dispositivo archivi un token di autenticazione nella memoria locale, dopo l’accesso dell'utente. Ciò garantisce un'esperienza completamente lineare, in quanto il dispositivo può recuperare il payload sicuro della notifica tramite questo token. Se invece l'applicazione non archivia i token di autenticazione nel dispositivo o se questi hanno una scadenza, l'app per dispositivo, alla ricezione della notifica push, dovrà visualizzare una notifica generica in cui si richiede all'utente di avviare l'app. L'app autentica quindi l'utente e mostra il payload di notifica.

Questa esercitazione descrive come inviare notifiche push sicure. Poiché i passaggi descritti in questa esercitazione si basano su quella relativa all' invio di notifiche agli utenti , sarà prima necessario completare i passaggi di quest'ultima.

Nota

In questa esercitazione si presuppone che l'utente abbia creato e configurato l'hub di notifica come descritto in Introduzione ad Hub di notifica (Android).

Progetto WebAPI

  1. In Visual Studio aprire il progetto AppBackend creato nell'esercitazione Notify Users (Inviare notifiche agli utenti).
  2. In Notifications.cs sostituire l'intera classe Notifications con il codice seguente. Assicurarsi di sostituire i segnaposto con la stringa di connessione con accesso completo per l'hub di notifica e il nome dell'hub. È possibile ottenere questi valori dal portale di Azure classico. Questo modulo rappresenta ora le diverse notifiche sicure che verranno inviate. In un'implementazione completa le notifiche verranno archiviate in un database; per semplicità, in questo caso, verranno archiviate in memoria.

     public class Notification
     {
         public int Id { get; set; }
         public string Payload { get; set; }
         public bool Read { get; set; }
     }
    
     public class Notifications
     {
         public static Notifications Instance = new Notifications();
    
         private List<Notification> notifications = new List<Notification>();
    
         public NotificationHubClient Hub { get; set; }
    
         private Notifications() {
             Hub = NotificationHubClient.CreateClientFromConnectionString("{conn string with full access}",     "{hub name}");
         }
    
         public Notification CreateNotification(string payload)
         {
             var notification = new Notification() {
             Id = notifications.Count,
             Payload = payload,
             Read = false
             };
    
             notifications.Add(notification);
    
             return notification;
         }
    
         public Notification ReadNotification(int id)
         {
             return notifications.ElementAt(id);
         }
     }
    
  3. In NotificationsController.cs sostituire il codice all'interno della definizione della classe NotificationsController con il codice seguente. Questo componente implementa un modo per il recupero della notifica da parte del dispositivo. Inoltre, ai fini di questa esercitazione, fornisce all'utente un modo per attivare un push sicuro ai propri dispositivi. Notare che a Hub di notifica verrà inviata una notifica non elaborata, che contiene l'ID della notifica senza alcun messaggio:

    public NotificationsController()
    {
        Notifications.Instance.CreateNotification("This is a secure notification!");
    }
    
    // GET api/notifications/id
    public Notification Get(int id)
    {
        return Notifications.Instance.ReadNotification(id);
    }
    
    public async Task<HttpResponseMessage> Post()
    {
        var secureNotificationInTheBackend = Notifications.Instance.CreateNotification("Secure confirmation.");
        var usernameTag = "username:" + HttpContext.Current.User.Identity.Name;
    
        // windows
        var rawNotificationToBeSent = new Microsoft.Azure.NotificationHubs.WindowsNotification(secureNotificationInTheBackend.Id.ToString(),
                        new Dictionary<string, string> {
                            {"X-WNS-Type", "wns/raw"}
                        });
        await Notifications.Instance.Hub.SendNotificationAsync(rawNotificationToBeSent, usernameTag);
    
        // apns
        await Notifications.Instance.Hub.SendAppleNativeNotificationAsync("{\"aps\": {\"content-available\": 1}, \"secureId\": \"" + secureNotificationInTheBackend.Id.ToString() + "\"}", usernameTag);
    
        // gcm
        await Notifications.Instance.Hub.SendGcmNativeNotificationAsync("{\"data\": {\"secureId\": \"" + secureNotificationInTheBackend.Id.ToString() + "\"}}", usernameTag);
    
         return Request.CreateResponse(HttpStatusCode.OK);
     }
    

Notare che il metodo Post non invia ora una notifica di tipo avviso popup, ma una notifica non elaborata che contiene solo l'ID notifica e non contenuto sensibile. Assicurarsi inoltre di impostare come commento l'operazione send per le piattaforme per le quali non sono configurate le credenziali nell'hub di notifica, in caso contrario verranno restituiti errori.

  1. L'app verrà ora nuovamente distribuita in un sito Web di Azure in modo da renderla accessibile da tutti i dispositivi. Fare clic con il pulsante destro del mouse sul progetto AppBackend e scegliere Pubblica.
  2. Selezionare un sito Web Azure come destinazione di pubblicazione. Accedere con l'account di Azure e selezionare un sito Web nuovo o esistente, quindi prendere nota della proprietà URL di destinazione nella scheda Connessione. Si farà riferimento a quest'URL come endpoint back-end più avanti in questa esercitazione. Fare clic su Pubblica.

Modificare il progetto Android

Ora che è stato modificato il back-end dell'app in modo da inviare solo l' ID di una notifica push, è necessario modificare l'app per Android in modo da gestire tale notifica e richiamare il back-end per recuperare il messaggio sicuro da visualizzare. Per conseguire questo obiettivo, è necessario assicurarsi che l'app per Android sia in grado di eseguire l'autenticazione con il back-end quando riceve le notifiche push.

Ora si modificherà il flusso di accesso per salvare il valore dell'intestazione di autenticazione nelle preferenze condivise dell'app. Un meccanismo analogo può essere usato per archiviare eventuali token di autenticazione (ad esempio token OAuth) che l'app dovrà usare senza richiedere le credenziali dell'utente.

  1. Nel progetto di app per Android, aggiungere le costanti seguenti all'inizio della classe MainActivity :

     public static final String NOTIFY_USERS_PROPERTIES = "NotifyUsersProperties";
     public static final String AUTHORIZATION_HEADER_PROPERTY = "AuthorizationHeader";
    
  2. Sempre nella classe MainActivity aggiornare il metodo getAuthorizationHeader() per includere il codice seguente:

     private String getAuthorizationHeader() throws UnsupportedEncodingException {
         EditText username = (EditText) findViewById(R.id.usernameText);
         EditText password = (EditText) findViewById(R.id.passwordText);
         String basicAuthHeader = username.getText().toString()+":"+password.getText().toString();
         basicAuthHeader = Base64.encodeToString(basicAuthHeader.getBytes("UTF-8"), Base64.NO_WRAP);
    
         SharedPreferences sp = getSharedPreferences(NOTIFY_USERS_PROPERTIES, Context.MODE_PRIVATE);
         sp.edit().putString(AUTHORIZATION_HEADER_PROPERTY, basicAuthHeader).commit();
    
         return basicAuthHeader;
     }
    
  3. Aggiungere le seguenti istruzioni import all'inizio del file MainActivity :

     import android.content.SharedPreferences;
    

A questo punto, modificare il gestore chiamato quando si riceve la notifica.

  1. Nella classe MyHandler modificare il metodo OnReceive() in modo che contenga:

     public void onReceive(Context context, Bundle bundle) {
         ctx = context;
         String secureMessageId = bundle.getString("secureId");
         retrieveNotification(secureMessageId);
     }
    
  2. Aggiungere quindi il metodo retrieveNotification(), sostituendo il segnaposto {back-end endpoint} con l'endpoint del back-end ottenuto durante la distribuzione del back-end:

     private void retrieveNotification(final String secureMessageId) {
         SharedPreferences sp = ctx.getSharedPreferences(MainActivity.NOTIFY_USERS_PROPERTIES, Context.MODE_PRIVATE);
         final String authorizationHeader = sp.getString(MainActivity.AUTHORIZATION_HEADER_PROPERTY, null);
    
         new AsyncTask<Object, Object, Object>() {
             @Override
             protected Object doInBackground(Object... params) {
                 try {
                     HttpUriRequest request = new HttpGet("{back-end endpoint}/api/notifications/"+secureMessageId);
                     request.addHeader("Authorization", "Basic "+authorizationHeader);
                     HttpResponse response = new DefaultHttpClient().execute(request);
                     if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                         Log.e("MainActivity", "Error retrieving secure notification" + response.getStatusLine().getStatusCode());
                         throw new RuntimeException("Error retrieving secure notification");
                     }
                     String secureNotificationJSON = EntityUtils.toString(response.getEntity());
                     JSONObject secureNotification = new JSONObject(secureNotificationJSON);
                     sendNotification(secureNotification.getString("Payload"));
                 } catch (Exception e) {
                     Log.e("MainActivity", "Failed to retrieve secure notification - " + e.getMessage());
                     return e;
                 }
                 return null;
             }
         }.execute(null, null, null);
     }
    

Questo metodo chiama il back-end dell'app per recuperare il contenuto della notifica usando le credenziali memorizzate nelle preferenze condivise e lo visualizza come una normale notifica. L'utente dell'app vedrà la notifica esattamente come qualsiasi altra notifica push.

Notare che è preferibile gestire i casi in cui manca la proprietà dell'intestazione di autenticazione o di rifiuto da parte del back-end. La gestione specifica di questi casi dipende in larga misura dall'esperienza dell'utente di destinazione. Una delle opzioni consiste nel visualizzare una notifica con un prompt generico affinché l'utente possa autenticarsi per recuperare la notifica effettiva.

Esecuzione dell'applicazione

Per eseguire l'applicazione, eseguire le operazioni seguenti:

  1. Assicurarsi che il progetto AppBackend sia distribuito in Azure. Se si usa Visual Studio, eseguire l'applicazione API Web AppBackend . Verrà visualizzata una pagina Web ASP.NET.
  2. In Eclipse eseguire l'app su un dispositivo Android fisico o sull'emulatore.
  3. Nell'interfaccia utente dell'app per Android immettere un nome utente e una password. Può trattarsi di qualsiasi stringa, ma devono avere lo stesso valore.
  4. Nell'interfaccia utente dell'app per Android fare clic su Log in. Fare clic su Send push.