Guia do desenvolvedor de Proteção de Informações do Windows (WIP)
Um aplicativo capacitado diferencia entre dados pessoais e empresariais e sabe o que proteger com base nas políticas Proteção de Informações do Windows (WIP) definidas pelo administrador.
Neste guia, mostraremos como criar uma. Quando você terminar, os administradores de política poderão confiar em seu aplicativo para consumir dados da organização. E os funcionários vão adorar saber que os dados pessoais deles ficarão intactos no dispositivo mesmo se eles cancelarem a inscrição do gerenciamento de dispositivo móvel (MDM) da organização ou saírem completamente da organização.
Observação Este guia ajuda você a capacitar um aplicativo UWP. Se você quiser habilitar um aplicativo de área de trabalho do Windows C++, consulte Guia do desenvolvedor de Proteção de Informações do Windows (WIP) (C++).
Você pode ler mais sobre WIP e aplicativos capacitados aqui: Proteção de Informações do Windows (WIP).
Você pode encontrar um exemplo completo aqui.
Se você estiver pronto para executar cada tarefa, vamos começar.
Primeiro, coletar o que você precisa
Você precisará do seguinte:
Uma VM (Máquina Virtual) de teste que executa o Windows 10, versão 1607 ou posterior. Você depurará seu aplicativo em relação a essa VM de teste.
Um computador de desenvolvimento que executa o Windows 10, versão 1607 ou posterior. Pode ser a VM de teste caso você tenha o Visual Studio instalado.
Configurar o ambiente de desenvolvimento
Você executará as seguintes tarefas:
Instalar o Assistente de Desenvolvedor de Instalação da WIP em sua VM de teste
Criar uma política de proteção usando o Assistente de desenvolvedor de instalação do WIP
Instalar o Assistente de desenvolvedor de instalação do WIP na VM de teste
Use essa ferramenta para configurar uma política de Proteção de Informações do Windows na VM de teste.
Baixe a ferramenta aqui: Assistente de desenvolvedor de instalação do WIP.
Crie uma política de proteção
Defina sua política adicionando informações a cada seção do Assistente de desenvolvedor de instalação do WIP. Escolha o ícone de ajuda ao lado de qualquer configuração para saber mais sobre como usá-lo.
Para obter diretrizes gerais sobre como usar essa ferramenta, consulte a seção Notas de versão na página de transferência do aplicativo.
Configurar um projeto do Visual Studio
No computador de desenvolvimento, abra seu projeto.
Adicione uma referência às extensões de desktop e móveis à Plataforma Universal do Windows (UWP).
Adicione esta funcionalidade ao seu arquivo de manifesto do pacote:
<rescap:Capability Name="enterpriseDataPolicy"/>
Leitura Opcional: o prefixo "rescap" significa Recurso Restrito. Consulte Funcionalidades especiais e restritas.
Adicione este namespace ao seu arquivo de manifesto do pacote:
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
Adicione o prefixo de namespace ao elemento
<ignorableNamespaces>
do seu arquivo de manifesto do pacote.<IgnorableNamespaces="uap mp rescap">
Dessa forma, se seu aplicativo for executado em uma versão do sistema operacional Windows que não dá suporte a funcionalidades restritas, o Windows irá ignorar a funcionalidade
enterpriseDataPolicy
.
Configurar depuração remota
Instale as Ferramentas Remotas para Visual Studio na VM de teste somente se você estiver desenvolvendo seu aplicativo em um computador que não seja a VM. Em seguida, no computador de desenvolvimento, inicie o depurador remoto e veja se seu aplicativo é executado na VM de teste.
Consulte Instruções para computador remoto.
Adicionar esses namespaces aos seus arquivos de código
Adicione estas instruções usando a parte superior de seus arquivos de código (os trechos de código neste guia as usam):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Security.EnterpriseData;
using Windows.Web.Http;
using Windows.Storage.Streams;
using Windows.ApplicationModel.DataTransfer;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml;
using Windows.ApplicationModel.Activation;
using Windows.Web.Http.Filters;
using Windows.Storage;
using Windows.Data.Xml.Dom;
using Windows.Foundation.Metadata;
using Windows.Web.Http.Headers;
Determinar o uso ou não das APIs do WIP em seu aplicativo
Certifique-se de que o sistema operacional que executa seu aplicativo suporta WIP e se WIP está ativado no dispositivo.
bool use_WIP_APIs = false;
if ((ApiInformation.IsApiContractPresent
("Windows.Security.EnterpriseData.EnterpriseDataContract", 3)
&& ProtectionPolicyManager.IsProtectionEnabled))
{
use_WIP_APIs = true;
}
else
{
use_WIP_APIs = false;
}
Não chame APIs de WIP se o sistema operacional não dá suporte à WIP ou WIP não está habilitado no dispositivo.
Ler dados empresariais
Para ler arquivos protegidos, pontos de extremidade de rede, dados da área de transferência e dados que você aceita de um contrato de compartilhamento, seu aplicativo precisará solicitar acesso.
Proteção de Informações do Windows dá ao aplicativo permissão caso seu aplicativo esteja na lista de permissões da política de proteção.
Nesta seção:
- Ler dados de um arquivo
- Ler dados de um ponto de extremidade de rede
- Ler dados da área de transferência
- Ler dados de um contrato de compartilhamento
Ler dados de um arquivo
Etapa 1: Obter o identificador de arquivo
Windows.Storage.StorageFolder storageFolder =
Windows.Storage.ApplicationData.Current.LocalFolder;
Windows.Storage.StorageFile file =
await storageFolder.GetFileAsync(fileName);
Etapa 2: Determinar se o seu aplicativo pode abrir o arquivo
Chame FileProtectionManager.GetProtectionInfoAsync para determinar se seu aplicativo pode abrir o arquivo.
FileProtectionInfo protectionInfo = await FileProtectionManager.GetProtectionInfoAsync(file);
if ((protectionInfo.Status != FileProtectionStatus.Protected &&
protectionInfo.Status != FileProtectionStatus.Unprotected))
{
return false;
}
else if (protectionInfo.Status == FileProtectionStatus.Revoked)
{
// Code goes here to handle this situation. Perhaps, show UI
// saying that the user's data has been revoked.
}
Um valor de FileProtectionStatus de Protegido significa que o arquivo está protegido e seu aplicativo pode abri-lo pois ele está na lista permitida da política.
Um valor de FileProtectionStatus de Desprotegido significa que o arquivo não está protegido e seu aplicativo pode abri-lo se não estiver na lista permitida de política.
APIs
FileProtectionManager.GetProtectionInfoAsync
FileProtectionInfo
FileProtectionStatus
ProtectionPolicyManager.IsIdentityManaged
Etapa 3: Ler o arquivo em um fluxo ou buffer
Ler o arquivo em um fluxo
var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
Ler o arquivo em um buffer
var buffer = await Windows.Storage.FileIO.ReadBufferAsync(file);
Ler dados de um ponto de extremidade de rede
Crie um contexto de thread protegido para ler de um ponto de extremidade empresarial.
Etapa 1: Obter a identidade do ponto de extremidade de rede
Uri resourceURI = new Uri("http://contoso.com/stockData.xml");
Windows.Networking.HostName hostName =
new Windows.Networking.HostName(resourceURI.Host);
string identity = await ProtectionPolicyManager.
GetPrimaryManagedIdentityForNetworkEndpointAsync(hostName);
Se o ponto de extremidade não for gerenciado por política, você receberá novamente uma cadeia de caracteres vazia.
APIs
ProtectionPolicyManager.GetPrimaryManagedIdentityForNetworkEndpointAsync
Etapa 2: Criar um contexto de thread protegido
Se o ponto de extremidade for gerenciado pela política, crie um contexto de thread protegido. Isso marca qualquer conexão de rede estabelecida no mesmo thread à identidade.
Ele também fornece acesso aos recursos de rede corporativa que são gerenciados por essa política.
if (!string.IsNullOrEmpty(identity))
{
using (ThreadNetworkContext threadNetworkContext =
ProtectionPolicyManager.CreateCurrentThreadNetworkContext(identity))
{
return await GetDataFromNetworkRedirectHelperMethod(resourceURI);
}
}
else
{
return await GetDataFromNetworkRedirectHelperMethod(resourceURI);
}
Este exemplo inclui chamadas de soquete em um bloco using
. Se você não fizer esse procedimento, certifique-se de fechar o contexto de thread depois de recuperar seu recurso. Consulte ThreadNetworkContext.Close.
Não crie nenhum arquivo pessoal nesse thread protegido porque esses arquivos serão criptografados automaticamente.
O método ProtectionPolicyManager.CreateCurrentThreadNetworkContext retorna um objeto ThreadNetworkContext, esteja o ponto de extremidade sendo gerenciado ou não pela política. Se seu aplicativo manipula recursos pessoais e empresariais, chame ProtectionPolicyManager.CreateCurrentThreadNetworkContext para todas as identidades. Depois de obter o recurso, descarte a ThreadNetworkContext para limpar todas as marcas de identidade do thread atual.
APIs
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity
ProtectionPolicyManager.CreateCurrentThreadNetworkContext
Etapa 3: Ler o recurso em um buffer
private static async Task<IBuffer> GetDataFromNetworkHelperMethod(Uri resourceURI)
{
HttpClient client;
client = new HttpClient();
try { return await client.GetBufferAsync(resourceURI); }
catch (Exception) { return null; }
}
(Opcional) Use um token de cabeçalho em vez de criar um contexto de conversa protegido
public static async Task<IBuffer> GetDataFromNetworkbyUsingHeader(Uri resourceURI)
{
HttpClient client;
Windows.Networking.HostName hostName =
new Windows.Networking.HostName(resourceURI.Host);
string identity = await ProtectionPolicyManager.
GetPrimaryManagedIdentityForNetworkEndpointAsync(hostName);
if (!string.IsNullOrEmpty(identity))
{
client = new HttpClient();
HttpRequestHeaderCollection headerCollection = client.DefaultRequestHeaders;
headerCollection.Add("X-MS-Windows-HttpClient-EnterpriseId", identity);
return await GetDataFromNetworkbyUsingHeaderHelperMethod(client, resourceURI);
}
else
{
client = new HttpClient();
return await GetDataFromNetworkbyUsingHeaderHelperMethod(client, resourceURI);
}
}
private static async Task<IBuffer> GetDataFromNetworkbyUsingHeaderHelperMethod(HttpClient client, Uri resourceURI)
{
try { return await client.GetBufferAsync(resourceURI); }
catch (Exception) { return null; }
}
Tratar redirecionamentos de página
Às vezes, um servidor Web redirecionará o tráfego para uma versão mais atual de um recurso.
Para lidar com isso, faça solicitações até que o status de resposta de sua solicitação tenha um valor de OK.
Em seguida, use o URI dessa resposta para obter a identidade do ponto de extremidade. Veja uma das maneiras de fazer isso:
private static async Task<IBuffer> GetDataFromNetworkRedirectHelperMethod(Uri resourceURI)
{
HttpClient client = null;
HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
filter.AllowAutoRedirect = false;
client = new HttpClient(filter);
HttpResponseMessage response = null;
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, resourceURI);
response = await client.SendRequestAsync(message);
if (response.StatusCode == HttpStatusCode.MultipleChoices ||
response.StatusCode == HttpStatusCode.MovedPermanently ||
response.StatusCode == HttpStatusCode.Found ||
response.StatusCode == HttpStatusCode.SeeOther ||
response.StatusCode == HttpStatusCode.NotModified ||
response.StatusCode == HttpStatusCode.UseProxy ||
response.StatusCode == HttpStatusCode.TemporaryRedirect ||
response.StatusCode == HttpStatusCode.PermanentRedirect)
{
message = new HttpRequestMessage(HttpMethod.Get, message.RequestUri);
response = await client.SendRequestAsync(message);
try { return await response.Content.ReadAsBufferAsync(); }
catch (Exception) { return null; }
}
else
{
try { return await response.Content.ReadAsBufferAsync(); }
catch (Exception) { return null; }
}
}
APIs
ProtectionPolicyManager.GetPrimaryManagedIdentityForNetworkEndpointAsync
ProtectionPolicyManager.CreateCurrentThreadNetworkContext
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity
Ler dados da área de transferência
Obter permissão para usar dados da área de transferência
Para obter dados da área de transferência, peça permissão ao Windows. Use DataPackageView.RequestAccessAsync para fazer isso.
public static async Task PasteText(TextBox textBox)
{
DataPackageView dataPackageView = Clipboard.GetContent();
if (dataPackageView.Contains(StandardDataFormats.Text))
{
ProtectionPolicyEvaluationResult result = await dataPackageView.RequestAccessAsync();
if (result == ProtectionPolicyEvaluationResult..Allowed)
{
string contentsOfClipboard = await dataPackageView.GetTextAsync();
textBox.Text = contentsOfClipboard;
}
}
}
Ocultar ou desabilitar os recursos que usam dados da área de transferência
Determine se a exibição atual tem permissão para acessar dados que estão na área de transferência.
Se isso não tiver, você poderá desabilitar ou ocultar os controles que permitem aos usuários colar informações da área de transferência ou visualizar seu conteúdo.
private bool IsClipboardAllowedAsync()
{
ProtectionPolicyEvaluationResult protectionPolicyEvaluationResult = ProtectionPolicyEvaluationResult.Blocked;
DataPackageView dataPackageView = Clipboard.GetContent();
if (dataPackageView.Contains(StandardDataFormats.Text))
protectionPolicyEvaluationResult =
ProtectionPolicyManager.CheckAccess(dataPackageView.Properties.EnterpriseId,
ProtectionPolicyManager.GetForCurrentView().Identity);
return (protectionPolicyEvaluationResult == ProtectionPolicyEvaluationResult.Allowed |
protectionPolicyEvaluationResult == ProtectionPolicyEvaluationResult.ConsentRequired);
}
APIs
ProtectionPolicyEvaluationResult
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity
Impedir que os usuários sejam avisados com uma caixa de diálogo de consentimento
Um novo documento não é pessoal nem empresarial. É apenas novo. Se um usuário colar os dados empresariais nele, o Windows aplicará a política e o usuário será avisado com uma caixa de diálogo de consentimento. Esse código impede que isso ocorra. Essa tarefa não pretende ajudar a proteger os dados. É mais sobre como impedir que os usuários recebam a caixa de diálogo de consentimento em casos em que seu aplicativo cria um novo item.
private async void PasteText(bool isNewEmptyDocument)
{
DataPackageView dataPackageView = Clipboard.GetContent();
if (dataPackageView.Contains(StandardDataFormats.Text))
{
if (!string.IsNullOrEmpty(dataPackageView.Properties.EnterpriseId))
{
if (isNewEmptyDocument)
{
ProtectionPolicyManager.TryApplyProcessUIPolicy(dataPackageView.Properties.EnterpriseId);
string contentsOfClipboard = contentsOfClipboard = await dataPackageView.GetTextAsync();
// add this string to the new item or document here.
}
else
{
ProtectionPolicyEvaluationResult result = await dataPackageView.RequestAccessAsync();
if (result == ProtectionPolicyEvaluationResult.Allowed)
{
string contentsOfClipboard = contentsOfClipboard = await dataPackageView.GetTextAsync();
// add this string to the new item or document here.
}
}
}
}
}
APIs
DataPackageView.RequestAccessAsync
ProtectionPolicyEvaluationResult
ProtectionPolicyManager.TryApplyProcessUIPolicy
Ler dados de um contrato de compartilhamento
Quando os funcionários escolhem seu aplicativo para compartilhar suas informações, seu aplicativo abre um novo item que contém esse conteúdo.
Como mencionamos anteriormente, um novo item não é pessoal nem empresarial. É apenas novo. Se seu código adicionar conteúdo empresarial ao item, o Windows aplicará a política e o usuário será avisado com uma caixa de diálogo de consentimento. Esse código impede que isso ocorra.
protected override async void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
{
bool isNewEmptyDocument = true;
string identity = "corp.microsoft.com";
ShareOperation shareOperation = args.ShareOperation;
if (shareOperation.Data.Contains(StandardDataFormats.Text))
{
if (!string.IsNullOrEmpty(shareOperation.Data.Properties.EnterpriseId))
{
if (isNewEmptyDocument)
// If this is a new and empty document, and we're allowed to access
// the data, then we can avoid popping the consent dialog
ProtectionPolicyManager.TryApplyProcessUIPolicy(shareOperation.Data.Properties.EnterpriseId);
else
{
// In this case, we can't optimize the workflow, so we just
// request consent from the user in this case.
ProtectionPolicyEvaluationResult protectionPolicyEvaluationResult = await shareOperation.Data.RequestAccessAsync();
if (protectionPolicyEvaluationResult == ProtectionPolicyEvaluationResult.Allowed)
{
string text = await shareOperation.Data.GetTextAsync();
// Do something with that text.
}
}
}
else
{
// If the data has no enterprise identity, then we already have access.
string text = await shareOperation.Data.GetTextAsync();
// Do something with that text.
}
}
}
APIs
ProtectionPolicyManager.RequestAccessAsync
ProtectionPolicyEvaluationResult
ProtectionPolicyManager.TryApplyProcessUIPolicy
Proteger dados empresariais
Protege dados empresariais que deixam o aplicativo. Os dados deixam seu aplicativo quando você os mostra em uma página, os salva em um arquivo ou um ponto de extremidade de rede ou por meio de um contrato de compartilhamento.
Nesta seção:
- Proteger dados que aparecem nas páginas
- Proteger dados em um arquivo como um processo em segundo plano
- Proteger parte de um arquivo
- Ler a parte protegida de um arquivo
- Proteger dados em uma pasta
- Proteger dados para um ponto de extremidade de rede
- Proteger dados que seu aplicativo compartilha por meio de um contrato de compartilhamento
- Proteger arquivos que você copia em outro local
- Proteger dados corporativos quando a tela do dispositivo está bloqueada
Proteger dados que aparecem nas páginas
Quando você mostra dados em uma página, informe ao Windows qual é o tipo dos dados (pessoais ou empresariais). Para fazer isso, marque a exibição atual do aplicativo ou todo o processo do aplicativo.
Quando você marca a exibição ou o processo, o Windows impõe a política nele. Isso ajuda a evitar a perda de dados resultante de ações que seu aplicativo não controla. Por exemplo, em um computador, um usuário pode usar CTRL-V para copiar informações corporativas de uma exibição e, em seguida, colá-las em outro aplicativo. O Windows protege contra isso. O Windows também ajuda a impor contratos de compartilhamento.
Marcar a exibição atual do aplicativo
Faça isso se seu aplicativo tiver várias exibições entre as quais algumas consomem dados empresariais e outras, dados pessoais.
// tag as enterprise data. "identity" the string that contains the enterprise ID.
// You'd get that from a file, network endpoint, or clipboard data package.
ProtectionPolicyManager.GetForCurrentView().Identity = identity;
// tag as personal data.
ProtectionPolicyManager.GetForCurrentView().Identity = String.Empty;
APIs
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity
Marcar o processo
Faça isso se todas as exibições do aplicativo trabalharem apenas com um tipo de dados (pessoais ou empresariais).
Isso evita a necessidade de gerenciar exibições marcadas de forma independente.
// tag as enterprise data. "identity" the string that contains the enterprise ID.
// You'd get that from a file, network endpoint, or clipboard data package.
bool result =
ProtectionPolicyManager.TryApplyProcessUIPolicy(identity);
// tag as personal data.
ProtectionPolicyManager.ClearProcessUIPolicy();
Proteger dados em um arquivo
Crie um arquivo protegido e, em seguida, grave-o.
Etapa 1: Determinar se o seu aplicativo pode criar um arquivo empresarial
Seu aplicativo pode criar um arquivo empresarial se a cadeia de caracteres de identidade for gerenciada por política e seu aplicativo estiver na lista de permissões da política.
if (!ProtectionPolicyManager.IsIdentityManaged(identity)) return false;
Etapa 2: Criar o arquivo e protegê-lo para a identidade
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFile storageFile = await storageFolder.CreateFileAsync("sample.txt",
CreationCollisionOption.ReplaceExisting);
FileProtectionInfo fileProtectionInfo =
await FileProtectionManager.ProtectAsync(storageFile, identity);
Etapa 3: Gravar esse fluxo ou buffer no arquivo
Gravar um fluxo
if (fileProtectionInfo.Status == FileProtectionStatus.Protected)
{
var stream = await storageFile.OpenAsync(FileAccessMode.ReadWrite);
using (var outputStream = stream.GetOutputStreamAt(0))
{
using (var dataWriter = new DataWriter(outputStream))
{
dataWriter.WriteString(enterpriseData);
}
}
}
Gravar um buffer
if (fileProtectionInfo.Status == FileProtectionStatus.Protected)
{
var buffer = Windows.Security.Cryptography.CryptographicBuffer.ConvertStringToBinary(
enterpriseData, Windows.Security.Cryptography.BinaryStringEncoding.Utf8);
await FileIO.WriteBufferAsync(storageFile, buffer);
}
Proteger dados em um arquivo como um processo em segundo plano
Esse código pode ser executado enquanto a tela do dispositivo está bloqueada. Se o administrador configurou uma política "Proteção de dados sob bloqueio" (DPL), o Windows removerá as chaves de criptografia necessárias para acessar recursos protegidos na memória do dispositivo. Isso impede vazamentos de dados se o dispositivo for perdido. O mesmo recurso também remove chaves associadas a arquivos protegidos quando seus identificadores são fechados.
Você precisará usar uma abordagem que mantém o identificador de arquivo aberto ao criar um arquivo.
Etapa 1: Determinar se você pode criar um arquivo empresarial
Você poderá criar um arquivo empresarial se a identidade que estiver usando for gerenciada por política e seu aplicativo estiver na lista de permissões da política.
if (!ProtectionPolicyManager.IsIdentityManaged(identity)) return false;
Etapa 2: Criar um arquivo e protegê-lo para a identidade
O FileProtectionManager.CreateProtectedAndOpenAsync cria um arquivo protegido e mantém o identificador de arquivo aberto enquanto você grava nele.
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
ProtectedFileCreateResult protectedFileCreateResult =
await FileProtectionManager.CreateProtectedAndOpenAsync(storageFolder,
"sample.txt", identity, CreationCollisionOption.ReplaceExisting);
Etapa 3: Gravar um fluxo ou um buffer no arquivo
Este exemplo grava um fluxo em um arquivo.
if (protectedFileCreateResult.ProtectionInfo.Status == FileProtectionStatus.Protected)
{
IOutputStream outputStream =
protectedFileCreateResult.Stream.GetOutputStreamAt(0);
using (DataWriter writer = new DataWriter(outputStream))
{
writer.WriteString(enterpriseData);
await writer.StoreAsync();
await writer.FlushAsync();
}
outputStream.Dispose();
}
else if (protectedFileCreateResult.ProtectionInfo.Status == FileProtectionStatus.AccessSuspended)
{
// Perform any special processing for the access suspended case.
}
APIs
ProtectedFileCreateResult.ProtectionInfo
FileProtectionStatus
ProtectedFileCreateResult.Stream
Proteger parte de um arquivo
Na maioria dos casos, é melhor armazenar dados pessoais e empresariais separadamente, mas você pode armazená-los no mesmo arquivo, se quiser. Por exemplo, o Microsoft Outlook pode armazenar emails empresariais juntamente com emails pessoais em um único arquivo morto.
Criptografe os dados empresariais, mas não todo o arquivo. Dessa forma, os usuários poderão continuar a usar esse arquivo mesmo se cancelarem o registro do MDM ou seus direitos de acesso a dados empresariais forem revogados. Além disso, seu aplicativo deve manter o controle de quais dados ele criptografa para que saiba quais dados proteger ao ler o arquivo na memória.
Etapa 1: Adicionar dados empresariais a um fluxo criptografado ou buffer
string enterpriseDataString = "<employees><employee><name>Bill</name><social>xxx-xxx-xxxx</social></employee></employees>";
var enterpriseData= Windows.Security.Cryptography.CryptographicBuffer.ConvertStringToBinary(
enterpriseDataString, Windows.Security.Cryptography.BinaryStringEncoding.Utf8);
BufferProtectUnprotectResult result =
await DataProtectionManager.ProtectAsync(enterpriseData, identity);
enterpriseData= result.Buffer;
APIs
DataProtectionManager.ProtectAsync
BufferProtectUnprotectResult.buffer
Etapa 2: Adicionar dados pessoais a um fluxo não criptografado ou buffer
string personalDataString = "<recipies><recipe><name>BillsCupCakes</name><cooktime>30</cooktime></recipe></recipies>";
var personalData = Windows.Security.Cryptography.CryptographicBuffer.ConvertStringToBinary(
personalDataString, Windows.Security.Cryptography.BinaryStringEncoding.Utf8);
Etapa 3: Gravar fluxos ou buffers em um arquivo
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFile storageFile = await storageFolder.CreateFileAsync("data.xml",
CreationCollisionOption.ReplaceExisting);
// Write both buffers to the file and save the file.
var stream = await storageFile.OpenAsync(FileAccessMode.ReadWrite);
using (var outputStream = stream.GetOutputStreamAt(0))
{
using (var dataWriter = new DataWriter(outputStream))
{
dataWriter.WriteBuffer(enterpriseData);
dataWriter.WriteBuffer(personalData);
await dataWriter.StoreAsync();
await outputStream.FlushAsync();
}
}
Etapa 4: Manter controle da localização dos dados empresariais no arquivo
É responsabilidade do seu aplicativo manter o controle dos dados que são empresariais nesse arquivo.
Você pode armazenar essas informações em uma propriedade associada ao arquivo, em um banco de dados ou em algum texto de cabeçalho no arquivo.
Neste exemplo, essas informações são salvas em um arquivo XML separado.
StorageFile metaDataFile = await storageFolder.CreateFileAsync("metadata.xml",
CreationCollisionOption.ReplaceExisting);
await Windows.Storage.FileIO.WriteTextAsync
(metaDataFile, "<EnterpriseDataMarker start='0' end='" + enterpriseData.Length.ToString() +
"'></EnterpriseDataMarker>");
Ler a parte protegida de um arquivo
Veja a seguir como você lerá os dados empresariais fora desse arquivo.
Etapa 1: Obter a posição de seus dados empresariais no arquivo
Windows.Storage.StorageFolder storageFolder =
Windows.Storage.ApplicationData.Current.LocalFolder;
Windows.Storage.StorageFile metaDataFile =
await storageFolder.GetFileAsync("metadata.xml");
string metaData = await Windows.Storage.FileIO.ReadTextAsync(metaDataFile);
XmlDocument doc = new XmlDocument();
doc.LoadXml(metaData);
uint startPosition =
Convert.ToUInt16((doc.FirstChild.Attributes.GetNamedItem("start")).InnerText);
uint endPosition =
Convert.ToUInt16((doc.FirstChild.Attributes.GetNamedItem("end")).InnerText);
Etapa 2: Abrir o arquivo de dados e certificar-se de que ele não esteja protegido
Windows.Storage.StorageFile dataFile =
await storageFolder.GetFileAsync("data.xml");
FileProtectionInfo protectionInfo =
await FileProtectionManager.GetProtectionInfoAsync(dataFile);
if (protectionInfo.Status == FileProtectionStatus.Protected)
return false;
APIs
FileProtectionManager.GetProtectionInfoAsync
FileProtectionInfo
FileProtectionStatus
Etapa 3: Ler dados empresariais do arquivo
var stream = await dataFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
stream.Seek(startPosition);
Windows.Storage.Streams.Buffer tempBuffer = new Windows.Storage.Streams.Buffer(50000);
IBuffer enterpriseData = await stream.ReadAsync(tempBuffer, endPosition, InputStreamOptions.None);
Etapa 4: Descriptografar o buffer que contém dados empresariais
DataProtectionInfo dataProtectionInfo =
await DataProtectionManager.GetProtectionInfoAsync(enterpriseData);
if (dataProtectionInfo.Status == DataProtectionStatus.Protected)
{
BufferProtectUnprotectResult result = await DataProtectionManager.UnprotectAsync(enterpriseData);
enterpriseData = result.Buffer;
}
else if (dataProtectionInfo.Status == DataProtectionStatus.Revoked)
{
// Code goes here to handle this situation. Perhaps, show UI
// saying that the user's data has been revoked.
}
APIs
DataProtectionInfo
DataProtectionManager.GetProtectionInfoAsync
Proteger dados em uma pasta
Você pode criar uma pasta e protegê-la. Dessa forma todos os itens que você adicionar à pasta serão automaticamente protegidos.
private async Task<bool> CreateANewFolderAndProtectItAsync(string folderName, string identity)
{
if (!ProtectionPolicyManager.IsIdentityManaged(identity)) return false;
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFolder newStorageFolder =
await storageFolder.CreateFolderAsync(folderName);
FileProtectionInfo fileProtectionInfo =
await FileProtectionManager.ProtectAsync(newStorageFolder, identity);
if (fileProtectionInfo.Status != FileProtectionStatus.Protected)
{
// Protection failed.
return false;
}
return true;
}
Certifique-se de que a pasta esteja vazia antes protegê-la. Você não pode proteger uma pasta que já contenha itens.
APIs
ProtectionPolicyManager.IsIdentityManaged
FileProtectionManager.ProtectAsync
FileProtectionInfo.Identity
FileProtectionInfo.Status
Proteger dados para um ponto de extremidade de rede
Crie um contexto de thread protegido para enviar esses dados a um ponto de extremidade empresarial.
Etapa 1: Obter a identidade do ponto de extremidade de rede
Windows.Networking.HostName hostName =
new Windows.Networking.HostName(resourceURI.Host);
string identity = await ProtectionPolicyManager.
GetPrimaryManagedIdentityForNetworkEndpointAsync(hostName);
APIs
ProtectionPolicyManager.GetPrimaryManagedIdentityForNetworkEndpointAsync
Etapa 2: Criar um contexto de thread protegido e enviar dados para o ponto de extremidade de rede
HttpClient client = null;
if (!string.IsNullOrEmpty(m_EnterpriseId))
{
ProtectionPolicyManager.GetForCurrentView().Identity = identity;
using (ThreadNetworkContext threadNetworkContext =
ProtectionPolicyManager.CreateCurrentThreadNetworkContext(identity))
{
client = new HttpClient();
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Put, resourceURI);
message.Content = new HttpStreamContent(dataToWrite);
HttpResponseMessage response = await client.SendRequestAsync(message);
if (response.StatusCode == HttpStatusCode.Ok)
return true;
else
return false;
}
}
else
{
return false;
}
APIs
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity
ProtectionPolicyManager.CreateCurrentThreadNetworkContext
Proteger dados que seu aplicativo compartilha por meio de um contrato de compartilhamento
Se você quiser que os usuários compartilhem conteúdo do seu aplicativo, precisará implementar um contrato de compartilhamento e manipular o evento DataTransferManager.DataRequested.
No manipulador de eventos, defina o contexto de identidade empresarial no pacote de dados.
private void OnShareSourceOperation(object sender, RoutedEventArgs e)
{
// Register the current page as a share source (or you could do this earlier in your app).
DataTransferManager.GetForCurrentView().DataRequested += OnDataRequested;
DataTransferManager.ShowShareUI();
}
private void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
if (!string.IsNullOrEmpty(this.shareSourceContent))
{
var protectionPolicyManager = ProtectionPolicyManager.GetForCurrentView();
DataPackage requestData = args.Request.Data;
requestData.Properties.Title = this.shareSourceTitle;
requestData.Properties.EnterpriseId = protectionPolicyManager.Identity;
requestData.SetText(this.shareSourceContent);
}
}
APIs
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity
Proteger arquivos que você copia em outro local
private async void CopyProtectionFromOneFileToAnother
(StorageFile sourceStorageFile, StorageFile targetStorageFile)
{
bool copyResult = await
FileProtectionManager.CopyProtectionAsync(sourceStorageFile, targetStorageFile);
if (!copyResult)
{
// Copying failed. To diagnose, you could check the file's status.
// (call FileProtectionManager.GetProtectionInfoAsync and
// check FileProtectionInfo.Status).
}
}
Proteger dados corporativos quando a tela do dispositivo está bloqueada
Remova todos os dados confidenciais na memória quando o dispositivo estiver bloqueado. Quando o usuário desbloqueia o dispositivo, seu aplicativo pode adicionar novamente esses dados com segurança.
Manipule o evento ProtectionPolicyManager.ProtectedAccessSuspending para que seu aplicativo saiba quando a tela estiver bloqueada. Esse evento será acionado somente se o administrador configurar uma proteção de dados seguros sob a política de bloqueio. O Windows remove temporariamente as chaves de proteção de dados provisionadas no dispositivo. O Windows remove essas chaves para garantir que não haja acesso não autorizado a dados criptografados enquanto o dispositivo está bloqueado e não está em poder de seu proprietário.
Manipule o evento ProtectionPolicyManager.ProtectedAccessResumed para que seu aplicativo saiba quando a tela está desbloqueada. Esse evento é acionado, independentemente de o administrador configurar ou não uma proteção de dados seguros sob política de bloqueio.
Remover dados confidenciais na memória quando a tela está bloqueada
Proteja dados confidenciais e feche todos os fluxos de arquivo que seu aplicativo tiver aberto em arquivos protegidos para ajudar a garantir que o sistema não armazena em cache dados confidenciais na memória.
Este exemplo salva o conteúdo de um bloco de texto em um buffer criptografado e remove o conteúdo desse bloco de texto.
private async void ProtectionPolicyManager_ProtectedAccessSuspending(object sender, ProtectedAccessSuspendingEventArgs e)
{
Deferral deferral = e.GetDeferral();
if (ProtectionPolicyManager.GetForCurrentView().Identity != String.Empty)
{
IBuffer documentBodyBuffer = CryptographicBuffer.ConvertStringToBinary
(documentTextBlock.Text, BinaryStringEncoding.Utf8);
BufferProtectUnprotectResult result = await DataProtectionManager.ProtectAsync
(documentBodyBuffer, ProtectionPolicyManager.GetForCurrentView().Identity);
if (result.ProtectionInfo.Status == DataProtectionStatus.Protected)
{
this.protectedDocumentBuffer = result.Buffer;
documentTextBlock.Text = null;
}
}
// Close any open streams that you are actively working with
// to make sure that we have no unprotected content in memory.
// Optionally, code goes here to use e.Deadline to determine whether we have more
// than 15 seconds left before the suspension deadline. If we do then process any
// messages queued up for sending while we are still able to access them.
deferral.Complete();
}
APIs
ProtectionPolicyManager.ProtectedAccessSuspending
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity
DataProtectionManager.ProtectAsync
BufferProtectUnprotectResult.buffer
ProtectedAccessSuspendingEventArgs.GetDeferral
Deferral.Complete
Adicionar dados confidenciais novamente quando o dispositivo for desbloqueado
ProtectionPolicyManager.ProtectedAccessResumed é acionado quando o dispositivo é desbloqueado e as chaves estão disponíveis novamente no dispositivo.
ProtectedAccessResumedEventArgs.Identities será uma coleção vazia se o administrador não tiver configurado uma proteção de dados seguros sob a política de bloqueio.
Este exemplo faz o inverso do exemplo anterior. Descriptografa o buffer, adiciona as informações desse buffer de volta para a caixa de texto e, em seguida, descarta o buffer.
private async void ProtectionPolicyManager_ProtectedAccessResumed(object sender, ProtectedAccessResumedEventArgs e)
{
if (ProtectionPolicyManager.GetForCurrentView().Identity != String.Empty)
{
BufferProtectUnprotectResult result = await DataProtectionManager.UnprotectAsync
(this.protectedDocumentBuffer);
if (result.ProtectionInfo.Status == DataProtectionStatus.Unprotected)
{
// Restore the unprotected version.
documentTextBlock.Text = CryptographicBuffer.ConvertBinaryToString
(BinaryStringEncoding.Utf8, result.Buffer);
this.protectedDocumentBuffer = null;
}
}
}
APIs
ProtectionPolicyManager.ProtectedAccessResumed
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity
DataProtectionManager.UnprotectAsync
BufferProtectUnprotectResult.Status
Manipular dados empresariais quando o conteúdo protegido for revogado
Se você deseja que seu aplicativo seja notificado quando a inscrição do dispositivo é cancelada do MDM ou quando o administrador de política revoga explicitamente o acesso aos dados empresariais, manipule o evento ProtectionPolicyManager_ProtectedContentRevoked.
Este exemplo determina se os dados em uma caixa de correio empresarial para um aplicativo de email foram revogados.
private string mailIdentity = "contoso.com";
void MailAppSetup()
{
ProtectionPolicyManager.ProtectedContentRevoked += ProtectionPolicyManager_ProtectedContentRevoked;
// Code goes here to set up mailbox for 'mailIdentity'.
}
private void ProtectionPolicyManager_ProtectedContentRevoked(object sender, ProtectedContentRevokedEventArgs e)
{
if (!new System.Collections.Generic.List<string>(e.Identities).Contains
(this.mailIdentity))
{
// This event is not for our identity.
return;
}
// Code goes here to delete any metadata associated with 'mailIdentity'.
}
Tópicos relacionados
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de