Guia do desenvolvedor da Proteção de Informações do Windows (WIP)
Um aplicativo habilitado diferencia entre dados corporativos e pessoais e sabe quais proteger com base nas políticas de Proteção de Informações do Windows (WIP) definidas pelo administrador.
Neste guia, mostraremos como criar um. Quando terminar, os administradores de política poderão confiar em seu aplicativo para consumir os 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 esclarecer um aplicativo UWP. Se você quiser habilitar um aplicativo da área de trabalho do Windows C++, consulte o guia do desenvolvedor da Proteção de Informações do Windows (WIP) (C++).
Você pode ler mais sobre WIP e aplicativos habilitados aqui: Proteção de Informações do Windows (WIP).
Você pode encontrar uma amostra completa aqui.
Se você estiver pronto para passar por cada tarefa, vamos começar.
Primeiro, reúna o que você precisa
Você precisará destes:
Uma VM (Máquina Virtual) de teste que executa o Windows 10, versão 1607 ou posterior. Você depurará seu aplicativo nessa VM de teste.
Um computador de desenvolvimento que executa o Windows 10, versão 1607 ou posterior. Essa pode ser sua VM de teste se você tiver o Visual Studio instalado nela.
Configurar seu ambiente de desenvolvimento
Você fará o seguinte:
Instale o Assistente do Desenvolvedor de Configuração da WIP em sua VM de teste
Criar uma política de proteção usando o Assistente do Desenvolvedor de Configuração da WIP
Instale o Assistente do Desenvolvedor de Configuração da WIP em sua VM de teste
Use essa ferramenta para configurar uma política de Proteção de Informações do Windows em sua VM de teste.
Baixe a ferramenta aqui: WIP Setup Developer Assistant.
Crie uma política de proteção
Defina sua política adicionando informações a cada seção no assistente de desenvolvedor de configuração da WIP. Escolha o ícone de ajuda ao lado de qualquer configuração para saber mais sobre como usá-la.
Para obter diretrizes mais gerais sobre como usar essa ferramenta, consulte a seção Notas de versão na página de download do aplicativo.
Configurar um projeto do Visual Studio
No computador de desenvolvimento, abra o projeto.
Adicione uma referência às extensões de desktop e móveis para a Plataforma Universal do Windows (UWP).
Adicione esse recurso ao arquivo de manifesto do pacote:
<rescap:Capability Name="enterpriseDataPolicy"/>
Leitura opcional: O prefixo "rescap" significa Capacidade Restrita. Consulte Recursos especiais e restritos.
Adicione este namespace ao arquivo de manifesto do pacote:
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
Adicione o prefixo de namespace ao elemento do arquivo de manifesto
<ignorableNamespaces>
do pacote.<IgnorableNamespaces="uap mp rescap">
Dessa forma, se o aplicativo for executado em uma versão do sistema operacional Windows que não dá suporte a recursos restritos, o Windows ignorará o
enterpriseDataPolicy
recurso.
Configurar depuração remota
Instale as Ferramentas Remotas do Visual Studio em sua VM de teste somente se você estiver desenvolvendo seu aplicativo em um computador diferente de sua VM. Em seguida, no computador de desenvolvimento, inicie o depurador remoto e veja se o aplicativo é executado na VM de teste.
Consulte as instruções do PC remoto.
Adicionar esses namespaces aos seus arquivos de código
Adicione-as instruções using à parte superior de seus arquivos de código (os snippets 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 se as APIs de WIP devem ser usadas em seu aplicativo
Verifique se o sistema operacional que executa seu aplicativo dá suporte à WIP e se a WIP está habilitada 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 WIP se o sistema operacional não der suporte a WIP ou se o WIP não estiver habilitado no dispositivo.
Leia dados corporativos
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.
A Proteção de Informações do Windows concederá permissão ao seu aplicativo se ele estiver na lista de permissões da política de proteção.
Nesta seção:
- Ler dados de um arquivo
- Ler dados de um endpoint 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 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 FileProtectionStatus de Protected significa que o arquivo está protegido e seu aplicativo pode abri-lo porque seu aplicativo está na lista de permissões da política.
Um valor FileProtectionStatus de UnProtected significa que o arquivo não está protegido e seu aplicativo pode abrir o arquivo mesmo que seu aplicativo não esteja na lista de permissões da 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 endpoint de rede
Crie um contexto de thread protegido para ler de um ponto de extremidade corporativo.
Etapa 1: Obter a identidade do endpoint 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 pela política, você receberá 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 todas as conexões de rede que você faz no mesmo thread para a identidade.
Ele também fornece acesso a recursos de rede corporativa 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 using
bloco. Se você não fizer isso, feche o contexto do thread depois de recuperar o 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 independentemente de o ponto de extremidade estar ou não sendo gerenciado pela política. Se o aplicativo lida com recursos pessoais e corporativos, chame ProtectionPolicyManager.CreateCurrentThreadNetworkContext para todas as identidades. Depois de obter o recurso, descarte o ThreadNetworkContext para limpar qualquer marca 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) Usar um token de cabeçalho em vez de criar um contexto de thread 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; }
}
Lidar com 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 da solicitação tenha um valor OK.
Em seguida, use o URI dessa resposta para obter a identidade do ponto de extremidade. Aqui está uma maneira 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 recursos que usam dados da área de transferência
Determine se o modo de exibição atual tem permissão para obter dados que estão na área de transferência.
Caso contrário, você pode desabilitar ou ocultar controles que permitem que os usuários colem informações da área de transferência ou visualizem 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 solicitados com uma caixa de diálogo de consentimento
Um novo documento não é pessoal ou empresarial. É apenas novo. Se um usuário colar dados corporativos nele, o Windows imporá a política e o usuário será solicitado com uma caixa de diálogo de consentimento. Este código impede que isso aconteça. Esta tarefa não é sobre ajudar a proteger os dados. Trata-se mais de impedir que os usuários recebam a caixa de diálogo de consentimento nos 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 escolherem seu aplicativo para compartilhar suas informações, seu aplicativo abrirá um novo item que contém esse conteúdo.
Como mencionamos anteriormente, um novo item não é pessoal ou empresarial. É apenas novo. Se o código adicionar conteúdo corporativo ao item, o Windows aplicará a política e o usuário será solicitado com uma caixa de diálogo de consentimento. Este código impede que isso aconteça.
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
Proteja os dados corporativos
Proteja os dados corporativos que saem do seu aplicativo. Os dados saem do aplicativo quando você os mostra em uma página, salva em um arquivo ou ponto de extremidade de rede ou por meio de um contrato de compartilhamento.
Nesta seção:
- Proteger dados que aparecem em 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 em um ponto de extremidade de rede
- Proteger os dados que seu aplicativo compartilha por meio de um contrato de compartilhamento
- Proteger arquivos que você copia para outro local
- Proteja os dados corporativos quando a tela do dispositivo estiver bloqueada
Proteger dados que aparecem em páginas
Quando você mostra dados em uma página, informe ao Windows que tipo de dados são (pessoais ou corporativos). Para fazer isso, marque a visualização do aplicativo atual ou marque todo o processo do aplicativo.
Quando você marca o modo de exibição ou o processo, o Windows impõe a política nele. Isso ajuda a evitar vazamentos de dados resultantes 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 um modo de exibição e colar essas informações em outro aplicativo. O Windows protege contra isso. O Windows também ajuda a impor contratos de compartilhamento.
Marcar a visualização atual do aplicativo
Faça isso se seu aplicativo tiver várias exibições em que algumas exibições consomem dados corporativos e outras consomem 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
Marque o processo
Faça isso se todas as exibições em seu aplicativo funcionarem com apenas um tipo de dados (pessoal ou corporativo).
Isso evita que você precise gerenciar visualizaçõ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 grave nele.
Etapa 1: determinar se seu aplicativo pode criar um arquivo corporativo
Seu aplicativo poderá criar um arquivo corporativo se a cadeia de caracteres de identidade for gerenciada pela política e seu aplicativo estiver na lista Permitido dessa 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
Escrever 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);
}
}
}
Escreva 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 estiver bloqueada. Se o administrador tiver configurado uma política segura de "Proteção de dados sob bloqueio" (DPL), o Windows removerá as chaves de criptografia necessárias para acessar recursos protegidos da memória do dispositivo. Isso evita vazamentos de dados se o dispositivo for perdido. Esse mesmo recurso também remove chaves associadas a arquivos protegidos quando seus identificadores são fechados.
Você terá que usar uma abordagem que mantenha o identificador de arquivo aberto ao criar um arquivo.
Etapa 1: Determinar se você pode criar um arquivo corporativo
Você poderá criar um arquivo corporativo se a identidade que você está usando for gerenciada pela política e seu aplicativo estiver na lista de permissões dessa 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 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, é mais fácil armazenar dados corporativos e pessoais separadamente, mas você pode armazená-los no mesmo arquivo, se desejar. Por exemplo, o Microsoft Outlook pode armazenar e-mails corporativos junto com e-mails pessoais em um único arquivo morto.
Criptografe os dados corporativos, mas não o arquivo inteiro. Dessa forma, os usuários podem continuar usando esse arquivo mesmo se cancelarem o registro do MDM ou se seus direitos de acesso a dados corporativos forem revogados. Além disso, seu aplicativo deve acompanhar quais dados ele criptografa para saber quais dados proteger ao ler o arquivo de volta na memória.
Etapa 1: Adicionar dados corporativos a um stream ou buffer criptografado
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 ou buffer não criptografado
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: acompanhar a localização dos dados da sua empresa no arquivo
É responsabilidade do seu aplicativo acompanhar os dados nesse arquivo que é de propriedade da empresa.
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.
Este exemplo salva essas informações 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 como você leria os dados corporativos desse arquivo.
Etapa 1: obter a posição dos dados da sua empresa 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: abra o arquivo de dados e verifique se ele não está 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 os dados da empresa 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 corporativos
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
Informações de proteção de dados
DataProtectionManager.GetProtectionInfoAsync
Proteger dados em uma pasta
Você pode criar uma pasta e protegê-la. Dessa forma, todos os itens adicionados a essa pasta são protegidos automaticamente.
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 de protegê-la. Não é possível proteger uma pasta que já contenha itens.
APIs
ProtectionPolicyManager.IsIdentityManaged
FileProtectionManager.ProtectAsync
FileProtectionInfo.Identity
FileProtectionInfo.Status
Proteger dados em um ponto de extremidade de rede
Crie um contexto de thread protegido para enviar esses dados para um endpoint corporativo.
Etapa 1: Obter a identidade do endpoint 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 os 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 corporativa 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 para 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).
}
}
Proteja os dados corporativos quando a tela do dispositivo estiver bloqueada
Remova todos os dados confidenciais da memória quando o dispositivo estiver bloqueado. Quando o usuário desbloqueia o dispositivo, seu aplicativo pode adicionar esses dados com segurança.
Manipule o evento ProtectionPolicyManager.ProtectedAccessSuspending para que seu aplicativo saiba quando a tela está bloqueada. Esse evento será gerado somente se o administrador configurar uma proteção de dados segura na 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 estiver bloqueado e possivelmente não estiver em posse de seu proprietário.
Manipule o evento ProtectionPolicyManager.ProtectedAccessResumed para que seu aplicativo saiba quando a tela está desbloqueada. Esse evento é gerado independentemente de o administrador configurar uma proteção de dados segura na política de bloqueio.
Remova dados confidenciais da memória quando a tela estiver bloqueada
Proteja dados confidenciais e feche todos os fluxos de arquivos que seu aplicativo abriu em arquivos protegidos para ajudar a garantir que o sistema não armazene em cache nenhum dado confidencial 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
Diferimento.Concluído
Adicionar de volta dados confidenciais quando o dispositivo for desbloqueado
ProtectionPolicyManager.ProtectedAccessResumed é gerado quando o dispositivo é desbloqueado e as chaves estão disponíveis no dispositivo novamente.
ProtectedAccessResumedEventArgs.Identities será uma coleção vazia se o administrador não tiver configurado uma proteção de dados segura na política de bloqueio.
Este exemplo faz o inverso do exemplo anterior. Ele descriptografa o buffer, adiciona informações desse buffer de volta à 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
Lidar com dados corporativos quando o conteúdo protegido for revogado
Se você quiser que seu aplicativo seja notificado quando o registro do dispositivo for cancelado do MDM ou quando o administrador da política revogar explicitamente o acesso aos dados corporativos, manipule o evento ProtectionPolicyManager_ProtectedContentRevoked.
Este exemplo determina se os dados em uma caixa de correio corporativa 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'.
}