Push Seguro dos Hubs de Notificação do Azure

Descrição Geral

O suporte de notificações push no Microsoft Azure permite-lhe aceder a uma infraestrutura push de escalamento horizontal de várias plataformas, de fácil utilização, que simplifica consideravelmente a implementação de notificações push para aplicações empresariais e de consumidor para plataformas móveis.

Devido a restrições regulamentares ou de segurança, por vezes uma aplicação pode querer incluir algo na notificação que não pode ser transmitido através da infraestrutura de notificação push padrão. Este tutorial descreve como alcançar a mesma experiência ao enviar informações confidenciais através de uma ligação segura e autenticada entre o dispositivo cliente e o back-end da aplicação.

A um nível elevado, o fluxo é o seguinte:

  1. O back-end da aplicação:
    • Armazena o payload seguro na base de dados de back-end.
    • Envia o ID desta notificação para o dispositivo (não são enviadas informações seguras).
  2. A aplicação no dispositivo, ao receber a notificação:
    • O dispositivo contacta o back-end a pedir o payload seguro.
    • A aplicação pode mostrar o payload como uma notificação no dispositivo.

É importante ter em atenção que, no fluxo anterior (e neste tutorial), assumimos que o dispositivo armazena um token de autenticação no armazenamento local, após o utilizador iniciar sessão. Isto garante uma experiência totalmente integrada, uma vez que o dispositivo pode obter o payload seguro da notificação com este token. Se a sua aplicação não armazenar tokens de autenticação no dispositivo ou se estes tokens puderem expirar, a aplicação do dispositivo, após receber a notificação, deverá apresentar uma notificação genérica a pedir ao utilizador para iniciar a aplicação. Em seguida, a aplicação autentica o utilizador e mostra o payload de notificação.

Este tutorial de Push Seguro mostra como enviar uma notificação push de forma segura. O tutorial baseia-se no tutorial Notificar Utilizadores , pelo que deve concluir primeiro os passos nesse tutorial.

Nota

Este tutorial pressupõe que criou e configurou o hub de notificação, conforme descrito em Enviar notificações push para aplicações iOS com os Hubs de Notificação do Azure.

Projeto WebAPI

  1. No Visual Studio, abra o projeto AppBackend que criou no tutorial Notificar Utilizadores .

  2. Em Notifications.cs, substitua toda a classe Notificações pelo seguinte código. Certifique-se de que substitui os marcadores de posição pela cadeia de ligação (com acesso total) para o hub de notificação e o nome do hub. Pode obter estes valores a partir do portal do Azure. Este módulo representa agora as diferentes notificações seguras que serão enviadas. Numa implementação completa, as notificações serão armazenadas numa base de dados; para simplificar, neste caso, armazenamo-los na memória.

     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. Em NotificationsController.cs, substitua o código dentro da definição de classe NotificationsController pelo seguinte código. Este componente implementa uma forma de o dispositivo obter a notificação de forma segura e também fornece uma forma (para efeitos deste tutorial) de acionar um push seguro para os seus dispositivos. Tenha em atenção que, ao enviar a notificação para o hub de notificação, apenas enviamos uma notificação não processada com o ID da notificação (e nenhuma mensagem real):

     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);
     }
    

Tenha em atenção que o Post método agora não envia uma notificação de alerta. Envia uma notificação não processada que contém apenas o ID de notificação e não qualquer conteúdo confidencial. Além disso, certifique-se de que comenta a operação de envio para as plataformas para as quais não tem credenciais configuradas no hub de notificação, uma vez que resultarão em erros.

  1. Agora, vamos implementar novamente esta aplicação num Site do Azure para torná-la acessível a partir de todos os dispositivos. Clique com o botão direito do rato no projeto AppBackend e selecione Publicar.
  2. Selecione Site do Azure como destino de publicação. Inicie sessão com a sua conta do Azure, selecione um Site existente ou novo e anote a propriedade URL de destino no separador Ligação . Iremos referir-nos a este URL como o ponto final de back-end mais adiante neste tutorial. Clique em Publish (Publicar).

Modificar o projeto iOS

Agora que modificou o back-end da aplicação para enviar apenas o ID de uma notificação, tem de alterar a aplicação iOS para processar essa notificação e ligar de volta para o back-end para obter a mensagem segura a apresentar.

Para atingir este objetivo, temos de escrever a lógica para obter o conteúdo seguro do back-end da aplicação.

  1. No AppDelegate.m, certifique-se de que a aplicação se regista para receber notificações silenciosas para processar o ID de notificação enviado a partir do back-end. Adicione a opção UIRemoteNotificationTypeNewsstandContentAvailability em didFinishLaunchingWithOptions:

    [[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeNewsstandContentAvailability];
    
  2. Na secção AppDelegate.m adicionar uma implementação na parte superior com a seguinte declaração:

    @interface AppDelegate ()
    - (void) retrieveSecurePayloadWithId:(int)payloadId completion: (void(^)(NSString*, NSError*)) completion;
    @end
    
  3. Em seguida, adicione na secção de implementação o seguinte código, substituindo o marcador {back-end endpoint} de posição pelo ponto final do back-end obtido anteriormente:

    NSString *const GetNotificationEndpoint = @"{back-end endpoint}/api/notifications";
    
    - (void) retrieveSecurePayloadWithId:(int)payloadId completion: (void(^)(NSString*, NSError*)) completion;
    {
        // check if authenticated
        ANHViewController* rvc = (ANHViewController*) self.window.rootViewController;
        NSString* authenticationHeader = rvc.registerClient.authenticationHeader;
        if (!authenticationHeader) return;
    
        NSURLSession* session = [NSURLSession
                                    sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
                                    delegate:nil
                                    delegateQueue:nil];
    
        NSURL* requestURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/%d", GetNotificationEndpoint, payloadId]];
        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:requestURL];
        [request setHTTPMethod:@"GET"];
        NSString* authorizationHeaderValue = [NSString stringWithFormat:@"Basic %@", authenticationHeader];
        [request setValue:authorizationHeaderValue forHTTPHeaderField:@"Authorization"];
    
        NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response;
            if (!error && httpResponse.statusCode == 200)
            {
                NSLog(@"Received secure payload: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    
                NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error: &error];
    
                completion([json objectForKey:@"Payload"], nil);
            }
            else
            {
                NSLog(@"Error status: %ld, request: %@", (long)httpResponse.statusCode, error);
                if (error)
                    completion(nil, error);
                else {
                    completion(nil, [NSError errorWithDomain:@"APICall" code:httpResponse.statusCode userInfo:nil]);
                }
            }
        }];
        [dataTask resume];
    }
    

    Este método chama o back-end da aplicação para obter o conteúdo de notificação com as credenciais armazenadas nas preferências partilhadas.

  4. Agora, processe a notificação recebida e utilize o método acima para obter o conteúdo a apresentar. Primeiro, ative a execução da aplicação iOS em segundo plano ao receber uma notificação push. No XCode, selecione o projeto da aplicação no painel esquerdo e, em seguida, clique no destino da aplicação principal na secção Destinos no painel central.

  5. Em seguida, clique no separador Capacidades na parte superior do painel central e selecione a caixa Notificações Remotas .

    Captura de ecrã do XCode, com o projeto de aplicação selecionado e o separador Capacidades aberto. A caixa de verificação Notificações remotas está selecionada.

  6. Em AppDelegate.m , adicione o seguinte método para processar notificações push:

    -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
    {
        NSLog(@"%@", userInfo);
    
        [self retrieveSecurePayloadWithId:[[userInfo objectForKey:@"secureId"] intValue] completion:^(NSString * payload, NSError *error) {
            if (!error) {
                // show local notification
                UILocalNotification* localNotification = [[UILocalNotification alloc] init];
                localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:0];
                localNotification.alertBody = payload;
                localNotification.timeZone = [NSTimeZone defaultTimeZone];
                [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
    
                completionHandler(UIBackgroundFetchResultNewData);
            } else {
                completionHandler(UIBackgroundFetchResultFailed);
            }
        }];
    
    }
    

    Tenha em atenção que é preferível processar os casos de rejeição ou propriedade do cabeçalho de autenticação em falta pelo back-end. O processamento específico destes casos depende principalmente da sua experiência de utilizador de destino. Uma opção é apresentar uma notificação com um pedido genérico para que o utilizador se autentique para obter a notificação real.

Executar a Aplicação

Para executar a aplicação, faça o seguinte:

  1. No XCode, execute a aplicação num dispositivo iOS físico (as notificações push não funcionarão no simulador).
  2. Na IU da aplicação iOS, introduza um nome de utilizador e uma palavra-passe. Podem ser qualquer cadeia, mas têm de ser o mesmo valor.
  3. Na IU da aplicação iOS, clique em Iniciar sessão. Em seguida, clique em Enviar push. Deverá ver a notificação segura a ser apresentada no centro de notificações.