Push seguro dos hubs de notificação do AzureAzure Notification Hubs Secure Push

Descrição geralOverview

O suporte à notificação por push no Microsoft Azure permite que você acesse uma infraestrutura de envio fácil de usar, multiplataforma e escalável, que simplifica bastante a implementação de notificações por push para aplicativos de consumidor e empresariais para dispositivos móveis compatíveis.Push notification support in Microsoft Azure enables you to access an easy-to-use, multi-platform, scaled-out push infrastructure, which greatly simplifies the implementation of push notifications for both consumer and enterprise applications for mobile platforms.

Devido a restrições normativas ou de segurança, às vezes um aplicativo pode querer incluir algo na notificação que não pode ser transmitido por meio da infraestrutura de notificação por push padrão.Due to regulatory or security constraints, sometimes an application might want to include something in the notification that cannot be transmitted through the standard push notification infrastructure. Este tutorial descreve como obter a mesma experiência ao enviar informações confidenciais por meio de uma conexão segura e autenticada entre o dispositivo cliente e o back-end do aplicativo.This tutorial describes how to achieve the same experience by sending sensitive information through a secure, authenticated connection between the client device and the app backend.

Em um alto nível, o fluxo é o seguinte:At a high level, the flow is as follows:

  1. O back-end do aplicativo:The app back-end:
    • Armazena a carga segura no banco de dados back-end.Stores secure payload in back-end database.
    • Envia a ID dessa notificação para o dispositivo (nenhuma informação segura é enviada).Sends the ID of this notification to the device (no secure information is sent).
  2. O aplicativo no dispositivo, ao receber a notificação:The app on the device, when receiving the notification:
    • O dispositivo entra em contato com o back-end solicitando a carga segura.The device contacts the back-end requesting the secure payload.
    • O aplicativo pode mostrar a carga como uma notificação no dispositivo.The app can show the payload as a notification on the device.

É importante observar que, no fluxo anterior (e neste tutorial), presumimos que o dispositivo armazene um token de autenticação no armazenamento local, depois que o usuário fizer logon.It is important to note that in the preceding flow (and in this tutorial), we assume that the device stores an authentication token in local storage, after the user logs in. Isso garante uma experiência simples, pois o dispositivo pode recuperar a carga segura da notificação usando esse token.This guarantees a seamless experience, as the device can retrieve the notification’s secure payload using this token. Se o seu aplicativo não armazenar tokens de autenticação no dispositivo ou se esses tokens puderem expirar, o aplicativo do dispositivo, após receber a notificação, deverá exibir uma notificação genérica solicitando que o usuário inicie o aplicativo.If your application does not store authentication tokens on the device, or if these tokens can be expired, the device app, upon receiving the notification should display a generic notification prompting the user to launch the app. Em seguida, o aplicativo autentica o usuário e mostra a carga de notificação.The app then authenticates the user and shows the notification payload.

Este tutorial de push seguro mostra como enviar uma notificação por push com segurança.This Secure Push tutorial shows how to send a push notification securely. O tutorial se baseia no tutorial notificar usuários , portanto, você deve concluir as etapas nesse tutorial primeiro.The tutorial builds on the Notify Users tutorial, so you should complete the steps in that tutorial first.

Nota

Este tutorial pressupõe que você criou e configurou seu hub de notificação conforme descrito em introdução com os hubs de notificação (Ios).This tutorial assumes that you have created and configured your notification hub as described in Getting Started with Notification Hubs (iOS).

Projeto WebAPIWebAPI Project

  1. No Visual Studio, abra o projeto AppBackend que você criou no tutorial notificar usuários .In Visual Studio, open the AppBackend project that you created in the Notify Users tutorial.

  2. No Notifications.cs, substitua toda a classe notificações pelo código a seguir.In Notifications.cs, replace the whole Notifications class with the following code. Certifique-se de substituir os espaços reservados pela sua cadeia de conexão (com acesso completo) para o Hub de notificação e o nome do Hub.Be sure to replace the placeholders with your connection string (with full access) for your notification hub, and the hub name. Você pode obter esses valores da portal do Azure.You can obtain these values from the Azure portal. Este módulo agora representa as diferentes notificações seguras que serão enviadas.This module now represents the different secure notifications that will be sent. Em uma implementação completa, as notificações serão armazenadas em um banco de dados; para simplificar, nesse caso, os armazenamos na memória.In a complete implementation, the notifications will be stored in a database; for simplicity, in this case we store them in memory.

     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. No NotificationsController.cs, substitua o código dentro da definição da classe NotificationsController pelo código a seguir.In NotificationsController.cs, replace the code inside the NotificationsController class definition with the following code. Esse componente implementa uma maneira de o dispositivo recuperar a notificação com segurança e também fornece uma maneira (para fins deste tutorial) disparar um envio seguro para seus dispositivos.This component implements a way for the device to retrieve the notification securely, and also provides a way (for the purposes of this tutorial) to trigger a secure push to your devices. Observe que, ao enviar a notificação para o Hub de notificação, enviamos apenas uma notificação bruta com a ID da notificação (e nenhuma mensagem real):Note that when sending the notification to the notification hub, we only send a raw notification with the ID of the notification (and no actual message):

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

Observe que o Post método agora não envia uma notificação do sistema.Note that the Post method now does not send a toast notification. Ele envia uma notificação bruta que contém apenas a ID de notificação e não qualquer conteúdo confidencial.It sends a raw notification that contains only the notification ID, and not any sensitive content. Além disso, lembre-se de comentar a operação de envio para as plataformas para as quais você não tem credenciais configuradas em seu hub de notificação, pois elas resultarão em erros.Also, make sure to comment the send operation for the platforms for which you do not have credentials configured on your notification hub, as they will result in errors.

  1. Agora vamos implantar novamente esse aplicativo em um site do Azure para torná-lo acessível de todos os dispositivos.Now we will re-deploy this app to an Azure Website in order to make it accessible from all devices. Clique com o botão direito do rato no projeto AppBackend e selecione Publicar.Right-click on the AppBackend project and select Publish.
  2. Selecione site do Azure como seu destino de publicação.Select Azure Website as your publish target. Entre com sua conta do Azure e selecione um site novo ou existente e anote a propriedade URL de destino na guia conexão . Vamos referir-nos a este URL como o ponto final do seu back-end mais adiante neste tutorial.Sign in with your Azure account and select an existing or new Website, and make a note of the destination URL property in the Connection tab. We will refer to this URL as your backend endpoint later in this tutorial. Clique em Publicar.Click Publish.

Modificar o projeto do iOSModify the iOS project

Agora que você modificou o back-end do aplicativo para enviar apenas a ID de uma notificação, você precisa alterar seu aplicativo IOS para lidar com essa notificação e retornar o back-end para recuperar a mensagem segura a ser exibida.Now that you modified your app back-end to send just the ID of a notification, you have to change your iOS app to handle that notification and call back your back-end to retrieve the secure message to be displayed.

Para atingir esse objetivo, precisamos escrever a lógica para recuperar o conteúdo seguro do back-end do aplicativo.To achieve this goal, we have to write the logic to retrieve the secure content from the app back-end.

  1. No AppDelegate.m, verifique se o aplicativo é registrado para notificações silenciosas para que ele processe a ID de notificação enviada do back-end.In AppDelegate.m, make sure the app registers for silent notifications so it processes the notification ID sent from the backend. Adicione a UIRemoteNotificationTypeNewsstandContentAvailability opção em didFinishLaunchingWithOptions:Add the UIRemoteNotificationTypeNewsstandContentAvailability option in didFinishLaunchingWithOptions:

    [[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeNewsstandContentAvailability];
    
  2. Na seção AppDelegate.m adicionar uma implementação na parte superior, com a seguinte declaração:In your AppDelegate.m add an implementation section at the top with the following declaration:

    @interface AppDelegate ()
    - (void) retrieveSecurePayloadWithId:(int)payloadId completion: (void(^)(NSString*, NSError*)) completion;
    @end
    
  3. Em seguida, adicione na seção de implementação o código a seguir, substituindo o espaço reservado {back-end endpoint} pelo ponto de extremidade do seu back-end obtido anteriormente:Then add in the implementation section the following code, substituting the placeholder {back-end endpoint} with the endpoint for your back-end obtained previously:

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

    Esse método chama o back-end do aplicativo para recuperar o conteúdo de notificação usando as credenciais armazenadas nas preferências compartilhadas.This method calls your app back-end to retrieve the notification content using the credentials stored in the shared preferences.

  4. Agora temos que lidar com a notificação de entrada e usar o método acima para recuperar o conteúdo a ser exibido.Now we have to handle the incoming notification and use the method above to retrieve the content to display. Primeiro, precisamos habilitar seu aplicativo iOS para ser executado em segundo plano ao receber uma notificação por push.First, we have to enable your iOS app to run in the background when receiving a push notification. No Xcode, selecione seu projeto de aplicativo no painel esquerdo e, em seguida, clique no destino do aplicativo principal na seção destinos do painel central.In XCode, select your app project on the left panel, then click your main app target in the Targets section from the central pane.

  5. Em seguida, clique na guia recursos na parte superior do painel central e marque a caixa de seleção notificações remotas .Then click your Capabilities tab at the top of your central pane, and check the Remote Notifications checkbox.

  6. Em AppDelegate.m adicionar o seguinte método para lidar com notificações por push:In AppDelegate.m add the following method to handle push notifications:

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

    Observe que é preferível manipular os casos de falta de propriedade de cabeçalho de autenticação ou rejeição pelo back-end.Note that it is preferable to handle the cases of missing authentication header property or rejection by the back-end. A manipulação específica desses casos depende principalmente da experiência do usuário de destino.The specific handling of these cases depends mostly on your target user experience. Uma opção é exibir uma notificação com um prompt genérico para que o usuário se autentique para recuperar a notificação real.One option is to display a notification with a generic prompt for the user to authenticate to retrieve the actual notification.

Executar o aplicativoRun the Application

Para executar o aplicativo, faça o seguinte:To run the application, do the following:

  1. No XCode, execute o aplicativo em um dispositivo iOS físico (as notificações por push não funcionarão no simulador).In XCode, run the app on a physical iOS device (push notifications will not work in the simulator).
  2. Na interface do usuário do aplicativo iOS, insira um nome de usuário e senha.In the iOS app UI, enter a username and password. Elas podem ser qualquer cadeia de caracteres, mas devem ter o mesmo valor.These can be any string, but they must be the same value.
  3. Na interface do usuário do aplicativo iOS, clique em fazer logon.In the iOS app UI, click Log in. Em seguida, clique em enviar envio por push.Then click Send push. Você deve ver a notificação segura sendo exibida no centro de notificações.You should see the secure notification being displayed in your notification center.