Windows Information Protection (WIP)-Entwicklerhandbuch
Eine optimierte App unterscheidet zwischen Unternehmens- und personenbezogenen Daten und weiß, welche basierend auf vom Administrator definierten Windows Information Protection (WIP)-Richtlinien geschützt werden sollen.
In diesem Leitfaden zeigen wir Ihnen, wie Sie eins erstellen. Wenn Sie fertig sind, können Richtlinienadministratoren Ihrer App vertrauen, um die Daten ihrer Organisation zu nutzen. Und Mitarbeiter schätzen es, dass ihre persönlichen Daten auf den Geräten unangetastet bleiben, auch wenn sie die Registrierung des Geräts in der mobilen Geräteverwaltung (Mobile Device Management, MDM) aufheben oder das Unternehmen ganz verlassen.
Hinweis Dieses Handbuch hilft Ihnen, eine UWP-App zu optimieren. Wenn Sie eine C++-Windows-Desktop-App optimieren möchten, lesen Sie das Windows Information Protection (WIP)-Entwicklerhandbuch (C++).
Weitere Informationen zu WIP und optimierten Apps finden Sie hier: Windows Information Protection (WIP).
Hier finden Sie ein vollständiges Beispiel.
Wenn Sie bereit sind, jede Aufgabe zu durchlaufen, beginnen wir.
Sammeln Sie zunächst, was Sie benötigen.
Sie benötigen die folgenden:
Ein virtueller Testcomputer (VM), der Windows 10, Version 1607 oder höher, ausführt. Sie debuggen Ihre App mit dieser Test-VM.
Ein Entwicklungscomputer mit Windows 10, Version 1607 oder höher. Dies könnte Ihre Test-VM sein, wenn Sie Visual Studio darauf installiert haben.
Einrichten Ihrer Entwicklungsumgebung
Sie führen die folgenden Aktionen aus:
Installieren des WIP Setup Developer Assistant auf Ihrer Test-VM
Erstellen einer Schutzrichtlinie mithilfe des WIP Setup Developer Assistant
Installieren des WIP Setup Developer Assistant auf Ihrer Test-VM
Verwenden Sie dieses Tool, um eine Windows Information Protection-Richtlinie auf Ihrem virtuellen Testcomputer einzurichten.
Laden Sie das Tool hier herunter: WIP Setup Developer Assistant.
Erstellen einer Schutzrichtlinie
Definieren Sie Ihre Richtlinie, indem Sie den einzelnen Abschnitten im WIP-Setup-Entwickler-Assistenten Informationen hinzufügen. Wählen Sie das Hilfesymbol neben einer beliebigen Einstellung aus, um mehr über die Verwendung zu erfahren.
Allgemeinere Anleitungen zur Verwendung dieses Tools finden Sie im Abschnitt "Versionsnotizen" auf der App-Downloadseite.
Einrichten eines Visual Studio-Projekts
Öffnen Sie auf Dem Entwicklungscomputer Ihr Projekt.
Fügen Sie einen Verweis auf die Desktop- und mobilen Erweiterungen für Universelle Windows-Plattform (UWP) hinzu.
Fügen Sie diese Funktion zur Paketmanifestdatei hinzu:
<rescap:Capability Name="enterpriseDataPolicy"/>
Optionales Lesen: Das Präfix "rescap" bedeutet eingeschränkte Funktion. Weitere Informationen finden Sie unter "Sonderfunktionen" und "Eingeschränkte Funktionen".
Fügen Sie diesen Namespace zur Paketmanifestdatei hinzu:
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
Fügen Sie dem Element der Paketmanifestdatei das
<ignorableNamespaces>
Namespacepräfix hinzu.<IgnorableNamespaces="uap mp rescap">
Wenn Ihre App auf eine Version des Windows-Betriebssystems ausgeführt wird, die keine eingeschränkten Funktionen unterstützt, ignoriert Windows die
enterpriseDataPolicy
Funktion.
Einrichten des Remotedebuggings
Installieren Sie Visual Studio Remote Tools nur dann auf Ihrem virtuellen Testcomputer, wenn Sie Ihre App auf einem anderen Computer als Ihrem virtuellen Computer entwickeln. Starten Sie dann auf Ihrem Entwicklungscomputer den Remotedebugger, und überprüfen Sie, ob Ihre App auf dem virtuellen Testcomputer ausgeführt wird.
Weitere Informationen finden Sie unter Remote-PC-Anweisungen.
Hinzufügen dieser Namespaces zu Ihren Codedateien
Fügen Sie diese using-Anweisungen am Anfang Ihrer Codedateien hinzu(Die Codeausschnitte in diesem Handbuch verwenden sie):
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;
Ermitteln, ob WIP-APIs in Ihrer App verwendet werden sollen
Stellen Sie sicher, dass das Betriebssystem, das Ihre App ausführt, WIP unterstützt und WIP auf dem Gerät aktiviert ist.
bool use_WIP_APIs = false;
if ((ApiInformation.IsApiContractPresent
("Windows.Security.EnterpriseData.EnterpriseDataContract", 3)
&& ProtectionPolicyManager.IsProtectionEnabled))
{
use_WIP_APIs = true;
}
else
{
use_WIP_APIs = false;
}
Rufen Sie keine WIP-APIs auf, wenn das Betriebssystem WIP oder WIP nicht unterstützt, auf dem Gerät nicht aktiviert ist.
Lesen von Unternehmensdaten
Zum Lesen geschützter Dateien, Netzwerkendpunkte, Zwischenablagedaten und Daten, die Sie von einem Freigabe-Vertrag akzeptieren, muss Ihre App Zugriff anfordern.
Windows Information Protection erteilt Ihrer App Die Berechtigung, wenn Ihre App in der Liste der zulässigen Schutzrichtlinien enthalten ist.
In diesem Abschnitt:
- Lesen von Daten aus einer Datei
- Lesen von Daten von einem Netzwerkendpunkt
- Lesen von Daten aus der Zwischenablage
- Lesen von Daten aus einem Freigabevertrag
Lesen von Daten aus einer Datei
Schritt 1: Abrufen des Dateihandles
Windows.Storage.StorageFolder storageFolder =
Windows.Storage.ApplicationData.Current.LocalFolder;
Windows.Storage.StorageFile file =
await storageFolder.GetFileAsync(fileName);
Schritt 2: Ermitteln, ob Ihre App die Datei öffnen kann
Rufen Sie FileProtectionManager.GetProtectionInfoAsync auf, um zu bestimmen, ob Ihre App die Datei öffnen kann.
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.
}
Ein FileProtectionStatus-Wert von Protected bedeutet, dass die Datei geschützt ist und Ihre App sie öffnen kann, da ihre App in der Liste der zulässigen Richtlinien enthalten ist.
Ein FileProtectionStatus-Wert von "UnProtected " bedeutet, dass die Datei nicht geschützt ist und Ihre App die Datei öffnen kann, auch wenn ihre App nicht in der Liste der zulässigen Richtlinien enthalten ist.
APIs
FileProtectionManager.GetProtectionInfoAsync
FileProtectionInfo
FileProtectionStatus
ProtectionPolicyManager.IsIdentityManaged
Schritt 3: Lesen der Datei in einen Datenstrom oder Puffer
Lesen der Datei in einen Datenstrom
var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
Lesen der Datei in einen Puffer
var buffer = await Windows.Storage.FileIO.ReadBufferAsync(file);
Lesen von Daten von einem Netzwerkendpunkt
Erstellen Sie einen geschützten Threadkontext zum Lesen von einem Unternehmensendpunkt.
Schritt 1: Abrufen der Identität des Netzwerkendpunkts
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);
Wenn der Endpunkt nicht durch eine Richtlinie verwaltet wird, erhalten Sie eine leere Zeichenfolge zurück.
APIs
ProtectionPolicyManager.GetPrimaryManagedIdentityForNetworkEndpointAsync
Schritt 2: Erstellen eines geschützten Threadkontexts
Wenn der Endpunkt durch eine Richtlinie verwaltet wird, erstellen Sie einen geschützten Threadkontext. Dadurch werden alle Netzwerkverbindungen markiert, die Sie im selben Thread mit der Identität herstellen.
Außerdem erhalten Sie Zugriff auf Unternehmensnetzwerkressourcen, die von dieser Richtlinie verwaltet werden.
if (!string.IsNullOrEmpty(identity))
{
using (ThreadNetworkContext threadNetworkContext =
ProtectionPolicyManager.CreateCurrentThreadNetworkContext(identity))
{
return await GetDataFromNetworkRedirectHelperMethod(resourceURI);
}
}
else
{
return await GetDataFromNetworkRedirectHelperMethod(resourceURI);
}
In diesem Beispiel werden Socketaufrufe in einen using
Block eingeschlossen. Wenn Sie dies nicht tun, stellen Sie sicher, dass Sie den Threadkontext schließen, nachdem Sie die Ressource abgerufen haben. Siehe ThreadNetworkContext.Close.
Erstellen Sie keine persönlichen Dateien in diesem geschützten Thread, da diese Dateien automatisch verschlüsselt werden.
Die ProtectionPolicyManager.CreateCurrentThreadNetworkContext-Methode gibt ein ThreadNetworkContext-Objekt zurück, unabhängig davon, ob der Endpunkt von der Richtlinie verwaltet wird. Wenn Ihre App sowohl persönliche als auch Unternehmensressourcen verarbeitet, rufen Sie ProtectionPolicyManager.CreateCurrentThreadNetworkContext für alle Identitäten auf. Nachdem Sie die Ressource abgerufen haben, löschen Sie den ThreadNetworkContext, um alle Identitätstags aus dem aktuellen Thread zu löschen.
APIs
ProtectionPolicyManager.GetForCurrentView
ProtectionPolicyManager.Identity
ProtectionPolicyManager.CreateCurrentThreadNetworkContext
Schritt 3: Lesen der Ressource in einen Puffer
private static async Task<IBuffer> GetDataFromNetworkHelperMethod(Uri resourceURI)
{
HttpClient client;
client = new HttpClient();
try { return await client.GetBufferAsync(resourceURI); }
catch (Exception) { return null; }
}
(Optional) Verwenden eines Headertokens anstelle eines geschützten Threadkontexts
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; }
}
Behandeln von Seitenumleitungen
Manchmal leitet ein Webserver den Datenverkehr zu einer aktuelleren Version einer Ressource um.
Um dies zu behandeln, stellen Sie Anforderungen vor, bis der Antwortstatus Ihrer Anforderung den Wert "OK" hat.
Verwenden Sie dann den URI dieser Antwort, um die Identität des Endpunkts abzurufen. Hier ist eine Möglichkeit, dies zu tun:
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
Lesen von Daten aus der Zwischenablage
Abrufen der Berechtigung zum Verwenden von Daten aus der Zwischenablage
Um Daten aus der Zwischenablage abzurufen, bitten Sie Windows um Erlaubnis. Verwenden Sie DataPackageView.RequestAccessAsync , um dies zu tun.
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;
}
}
}
Ausblenden oder Deaktivieren von Features, die Zwischenablagedaten verwenden
Bestimmen Sie, ob die aktuelle Ansicht über die Berechtigung zum Abrufen von Daten verfügt, die sich in der Zwischenablage befinden.
Andernfalls können Sie Steuerelemente deaktivieren oder ausblenden, mit denen Benutzer Informationen aus der Zwischenablage einfügen oder deren Inhalt in der Vorschau anzeigen können.
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
Verhindern, dass Benutzer mit einem Zustimmungsdialogfeld aufgefordert werden
Ein neues Dokument ist nicht persönlich oder unternehmensisch. Es ist nur neu. Wenn ein Benutzer Unternehmensdaten in diese einfüge, erzwingt Windows die Richtlinie, und der Benutzer wird mit einem Zustimmungsdialogfeld aufgefordert. Dieser Code verhindert, dass dies geschieht. Bei dieser Aufgabe geht es nicht darum, Daten zu schützen. Es geht mehr darum, benutzer daran zu hindern, das Zustimmungsdialogfeld in Fällen zu erhalten, in denen Ihre App ein völlig neues Element erstellt.
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
Lesen von Daten aus einem Freigabevertrag
Wenn Mitarbeiter Ihre App auswählen, um ihre Informationen freizugeben, öffnet Ihre App ein neues Element, das diesen Inhalt enthält.
Wie bereits erwähnt, ist ein neues Element nicht persönlich oder unternehmensisch. Es ist nur neu. Wenn Ihr Code dem Element Unternehmensinhalte hinzufügt, erzwingt Windows die Richtlinie, und der Benutzer wird mit einem Zustimmungsdialogfeld aufgefordert. Dieser Code verhindert, dass dies geschieht.
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
Schützen von Unternehmensdaten
Schützen Sie Unternehmensdaten, die Ihre App verlassen. Daten verlassen Ihre App, wenn Sie sie auf einer Seite anzeigen, sie in einer Datei oder einem Netzwerkendpunkt oder über einen Freigabevertrag speichern.
In diesem Abschnitt:
- Schützen von Daten, die auf Seiten angezeigt werden
- Schützen von Daten in einer Datei als Hintergrundprozess
- Schützen eines Teils einer Datei
- Lesen des geschützten Teils einer Datei
- Schützen von Daten in einem Ordner
- Schützen von Daten an einem Netzwerkendpunkt
- Schützen von Daten, die Ihre App über einen Freigabevertrag teilt
- Schützen von Dateien, die Sie an einen anderen Speicherort kopieren
- Schützen von Unternehmensdaten, wenn der Bildschirm des Geräts gesperrt ist
Schützen von Daten, die auf Seiten angezeigt werden
Wenn Sie Daten auf einer Seite anzeigen, teilen Sie Windows mit, welche Art von Daten es sich handelt (persönlich oder Unternehmensdaten). Markieren Sie dazu die aktuelle App-Ansicht, oder markieren Sie den gesamten App-Prozess.
Wenn Sie die Ansicht oder den Prozess markieren, erzwingt Windows die Richtlinie. Dadurch können Datenlecks verhindert werden, die sich aus Aktionen ergeben, die Ihre App nicht steuert. Beispielsweise könnte ein Benutzer auf einem Computer STRG-V verwenden, um Unternehmensinformationen aus einer Ansicht zu kopieren und diese Informationen dann in eine andere App einzufügen. Windows schützt davor. Windows hilft auch beim Erzwingen von Freigabeverträgen.
Markieren der aktuellen App-Ansicht
Führen Sie dies aus, wenn Ihre App über mehrere Ansichten verfügt, in denen einige Ansichten Unternehmensdaten nutzen und einige personenbezogene Daten nutzen.
// 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
Markieren des Prozesses
Führen Sie dies aus, wenn alle Ansichten in Ihrer App nur mit einem Datentyp (persönlich oder Unternehmenstyp) funktionieren.
Dadurch wird verhindert, dass Sie unabhängig markierte Ansichten verwalten müssen.
// 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();
Schützen von Daten in einer Datei
Erstellen Sie eine geschützte Datei, und schreiben Sie sie dann.
Schritt 1: Ermitteln, ob Ihre App eine Unternehmensdatei erstellen kann
Ihre App kann eine Unternehmensdatei erstellen, wenn die Identitätszeichenfolge anhand einer Richtlinie verwaltet wird und ihre App sich in der Liste der zulässigen Richtlinien befindet.
if (!ProtectionPolicyManager.IsIdentityManaged(identity)) return false;
Schritt 2: Erstellen der Datei und Schützen der Datei für die Identität
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
StorageFile storageFile = await storageFolder.CreateFileAsync("sample.txt",
CreationCollisionOption.ReplaceExisting);
FileProtectionInfo fileProtectionInfo =
await FileProtectionManager.ProtectAsync(storageFile, identity);
Schritt 3: Schreiben dieses Datenstroms oder Puffers in die Datei
Schreiben eines Datenstroms
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);
}
}
}
Schreiben eines Puffers
if (fileProtectionInfo.Status == FileProtectionStatus.Protected)
{
var buffer = Windows.Security.Cryptography.CryptographicBuffer.ConvertStringToBinary(
enterpriseData, Windows.Security.Cryptography.BinaryStringEncoding.Utf8);
await FileIO.WriteBufferAsync(storageFile, buffer);
}
Schützen von Daten in einer Datei als Hintergrundprozess
Dieser Code kann ausgeführt werden, während der Bildschirm des Geräts gesperrt ist. Wenn der Administrator eine sichere Richtlinie "Datenschutz unter Sperre" (Data Protection under lock, DPL) konfiguriert hat, entfernt Windows die Verschlüsselungsschlüssel, die für den Zugriff auf geschützte Ressourcen aus dem Gerätespeicher erforderlich sind. Dadurch werden Datenlecks verhindert, wenn das Gerät verloren geht. Dieses Feature entfernt auch Schlüssel, die mit geschützten Dateien verknüpft sind, wenn ihre Handles geschlossen werden.
Sie müssen einen Ansatz verwenden, der das Dateihandle geöffnet hält, wenn Sie eine Datei erstellen.
Schritt 1: Ermitteln, ob Sie eine Unternehmensdatei erstellen können
Sie können eine Unternehmensdatei erstellen, wenn die von Ihnen verwendete Identität anhand einer Richtlinie verwaltet wird und ihre App sich in der Liste der zulässigen Richtlinien befindet.
if (!ProtectionPolicyManager.IsIdentityManaged(identity)) return false;
Schritt 2: Erstellen einer Datei und Schützen der Datei für die Identität
Der FileProtectionManager.CreateProtectedAndOpenAsync erstellt eine geschützte Datei und hält das Dateihandle geöffnet, während Sie darauf schreiben.
StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
ProtectedFileCreateResult protectedFileCreateResult =
await FileProtectionManager.CreateProtectedAndOpenAsync(storageFolder,
"sample.txt", identity, CreationCollisionOption.ReplaceExisting);
Schritt 3: Schreiben eines Datenstroms oder Puffers in die Datei
In diesem Beispiel wird ein Datenstrom in eine Datei geschrieben.
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
Schützen eines Teils einer Datei
In den meisten Fällen ist es sauberer, Unternehmens- und persönliche Daten separat zu speichern, aber Sie können sie bei Bedarf in derselben Datei speichern. Beispielsweise kann Microsoft Outlook Unternehmens-Mails zusammen mit persönlichen E-Mails in einer einzigen Archivdatei speichern.
Verschlüsseln Sie die Unternehmensdaten, aber nicht die gesamte Datei. Auf diese Weise können Benutzer diese Datei weiterhin verwenden, auch wenn sie die Registrierung von MDM aufheben oder ihre Unternehmensdatenzugriffsrechte widerrufen werden. Außerdem sollte Ihre App nachverfolgen, welche Daten verschlüsselt werden, damit sie weiß, welche Daten geschützt werden sollen, wenn sie die Datei wieder in den Arbeitsspeicher liest.
Schritt 1: Hinzufügen von Unternehmensdaten zu einem verschlüsselten Datenstrom oder Puffer
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
Schritt 2: Hinzufügen personenbezogener Daten zu einem unverschlüsselten Datenstrom oder Puffer
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);
Schritt 3: Schreiben von Datenströmen oder Puffern in eine Datei
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();
}
}
Schritt 4: Nachverfolgen des Speicherorts Ihrer Unternehmensdaten in der Datei
Es liegt in der Verantwortung Ihrer App, die Daten in dieser Datei im Besitz des Unternehmens nachzuverfolgen.
Sie können diese Informationen in einer Eigenschaft speichern, die der Datei, einer Datenbank oder in einem Headertext in der Datei zugeordnet ist.
In diesem Beispiel werden diese Informationen in einer separaten XML-Datei gespeichert.
StorageFile metaDataFile = await storageFolder.CreateFileAsync("metadata.xml",
CreationCollisionOption.ReplaceExisting);
await Windows.Storage.FileIO.WriteTextAsync
(metaDataFile, "<EnterpriseDataMarker start='0' end='" + enterpriseData.Length.ToString() +
"'></EnterpriseDataMarker>");
Lesen des geschützten Teils einer Datei
Hier erfahren Sie, wie Sie die Unternehmensdaten aus dieser Datei lesen.
Schritt 1: Abrufen der Position Ihrer Unternehmensdaten in der Datei
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);
Schritt 2: Öffnen Sie die Datendatei, und stellen Sie sicher, dass sie nicht geschützt ist.
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
Schritt 3: Lesen der Unternehmensdaten aus der Datei
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);
Schritt 4: Entschlüsseln des Puffers, der Unternehmensdaten enthält
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
Schützen von Daten in einem Ordner
Sie können einen Ordner erstellen und schützen. Auf diese Weise werden alle Elemente, die Sie diesem Ordner hinzufügen, automatisch geschützt.
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;
}
Stellen Sie sicher, dass der Ordner leer ist, bevor Sie ihn schützen. Sie können einen Ordner, der bereits Elemente enthält, nicht schützen.
APIs
ProtectionPolicyManager.IsIdentityManaged
FileProtectionManager.ProtectAsync
FileProtectionInfo.Identity
FileProtectionInfo.Status
Schützen von Daten an einem Netzwerkendpunkt
Erstellen Sie einen geschützten Threadkontext, um diese Daten an einen Unternehmensendpunkt zu senden.
Schritt 1: Abrufen der Identität des Netzwerkendpunkts
Windows.Networking.HostName hostName =
new Windows.Networking.HostName(resourceURI.Host);
string identity = await ProtectionPolicyManager.
GetPrimaryManagedIdentityForNetworkEndpointAsync(hostName);
APIs
ProtectionPolicyManager.GetPrimaryManagedIdentityForNetworkEndpointAsync
Schritt 2: Erstellen eines geschützten Threadkontexts und Senden von Daten an den Netzwerkendpunkt
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
Schützen von Daten, die Ihre App über einen Freigabevertrag teilt
Wenn Benutzer Inhalte aus Ihrer App freigeben möchten, müssen Sie einen Freigabe-Vertrag implementieren und das DataTransferManager.DataRequested-Ereignis behandeln.
Legen Sie im Ereignishandler den Unternehmensidentitätskontext im Datenpaket fest.
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
Schützen von Dateien, die Sie an einen anderen Speicherort kopieren
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).
}
}
Schützen von Unternehmensdaten, wenn der Bildschirm des Geräts gesperrt ist
Entfernen Sie alle vertraulichen Daten im Arbeitsspeicher, wenn das Gerät gesperrt ist. Wenn der Benutzer das Gerät entsperrt, kann Ihre App diese Daten sicher wieder hinzufügen.
Behandeln Sie das ProtectionPolicyManager.ProtectedAccessSuspending-Ereignis , damit Ihre App weiß, wann der Bildschirm gesperrt ist. Dieses Ereignis wird nur ausgelöst, wenn der Administrator einen sicheren Datenschutz unter Sperrrichtlinie konfiguriert. Windows entfernt vorübergehend die Datenschutzschlüssel, die auf dem Gerät bereitgestellt werden. Windows entfernt diese Schlüssel, um sicherzustellen, dass kein nicht autorisierter Zugriff auf verschlüsselte Daten vorhanden ist, während das Gerät gesperrt ist und möglicherweise nicht im Besitz seines Besitzers ist.
Behandeln Sie das ProtectionPolicyManager.ProtectedAccessResumed-Ereignis , damit Ihre App weiß, wann der Bildschirm entsperrt ist. Dieses Ereignis wird unabhängig davon ausgelöst, ob der Administrator einen sicheren Datenschutz unter Sperre konfiguriert.
Entfernen vertraulicher Daten im Arbeitsspeicher, wenn der Bildschirm gesperrt ist
Schützen Sie vertrauliche Daten, und schließen Sie alle Dateidatenströme, die Ihre App in geschützten Dateien geöffnet hat, um sicherzustellen, dass das System keine vertraulichen Daten im Arbeitsspeicher zwischenspeichert.
In diesem Beispiel werden Inhalte aus einem Textblock in einem verschlüsselten Puffer gespeichert und der Inhalt aus diesem Textblock entfernt.
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
Hinzufügen vertraulicher Daten, wenn das Gerät entsperrt ist
ProtectionPolicyManager.ProtectedAccessResumed wird ausgelöst, wenn das Gerät entsperrt ist und die Schlüssel wieder auf dem Gerät verfügbar sind.
ProtectedAccessResumedEventArgs.Identities ist eine leere Sammlung, wenn der Administrator keinen sicheren Datenschutz unter Sperrrichtlinie konfiguriert hat.
In diesem Beispiel wird das vorherige Beispiel umgekehrt. Er entschlüsselt den Puffer, fügt dem Textfeld Informationen aus diesem Puffer hinzu und entfernt dann den Puffer.
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
Behandeln von Unternehmensdaten, wenn geschützte Inhalte widerrufen werden
Wenn Ihre App benachrichtigt werden soll, wenn das Gerät von MDM nicht registriert ist oder der Richtlinienadministrator den Zugriff auf Unternehmensdaten explizit widerruft, behandeln Sie das ProtectionPolicyManager_ProtectedContentRevoked Ereignis.
In diesem Beispiel wird ermittelt, ob die Daten in einem Unternehmenspostfach für eine E-Mail-App widerrufen wurden.
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'.
}