💡 Pełny działający przykład dostępny na GitHubie:
remove-pii-from-office-metadata-java

Wyzwanie zgodności: Dlaczego ręczna weryfikacja metadanych nie sprawdza się w dużej skali

Zespół ds. rekordów wysyła 200 dokumentów do zewnętrznego audytora. Ktoś przeczytał każdą stronę. Nikt nie przeglądał właściwości, a to właśnie w nich znajdują się dane osobowe: analityk w polu Author, drugi analityk w LastSavedBy, szef działu w Manager, spółka zależna w Company, znacznik czasu LastPrinted z nocy przed terminem oraz, w przypadku wszystkiego, co przeszło przez SharePoint, identyfikator zatwierdzającego i ścieżka workflow.

Sanityzacja metadanych to przepływ pracy GroupDocs.Metadata dla Javy, który usuwa te właściwości zawierające tożsamość z plików Word, Excel i PowerPoint, a następnie odczytuje wynik, aby zgłosić to, co przetrwało. Ten artykuł przechodzi przez przepływ pracy, jaki zespół ds. zgodności zbudowałby: jakie grupy właściwości istnieją, które reguły usuwania pasują do każdej z nich, kiedy pełne wyczyszczenie zastępuje ukierunkowane przejścia i dlaczego weryfikacja powinna należeć do tego samego zadania, a nie do listy kontrolnej.

Problem skali nie polega na tym, że usuwanie jest trudne. Polega na tym, że ręczna weryfikacja nie generuje zapisu. Audytor pytający „które pola zostały usunięte z tego pliku i kiedy” potrzebuje liczby, a okno właściwości nie dostarcza żadnych danych.

Dlaczego ogólne narzędzia czyszczące nie działają tutaj

Okno właściwości systemu Windows edytuje jeden plik naraz i obejmuje jedynie podzbiór pól. Inspektor dokumentów Office działa interaktywnie, co wyklucza go z nocnych zadań. Oba pozostawiają nietknięte niestandardowe części OOXML i żaden z nich nie zapisuje nic, co potok mógłby odczytać ponownie.

Zespoły, które schodzą o poziom niżej, edytując bezpośrednio docProps/core.xml i docProps/custom.xml, biorą na siebie ciężar utrzymania: wyrażenie XPath na każde pole, na każdy format, które trzeba ponownie przeglądać za każdym razem, gdy aplikacja generująca zmieni nazwę. Ta praca także nie rozwiązuje problemu klasyfikacji. Nazwy właściwości różnią się w zależności od pakietu, więc lista nazw cicho staje się nieaktualna, a reguła, która już nie pasuje, wygląda tak samo jak plik, który był już czysty.

Rozwiązanie: GroupDocs.Metadata w przepływie pracy rekordów

GroupDocs.Metadata dla Javy przetwarza wszystko przez jeden silnik wyszukiwania właściwości. Obiekt Specification decyduje, które właściwości pasują, removeProperties usuwa każde dopasowanie i zwraca liczbę zmienionych, a findProperties uruchamia ten sam predykat w trybie tylko do odczytu. Właściwości noszą tagi, więc Tags.getPerson().getCreator() identyfikuje pola typu autor, niezależnie od formatu czy pakietu, z którego pochodzą.

Java nie ma przeciążenia lambda dla removeProperties, co okazuje się tutaj zaletą: każda reguła jest obiektem i obiekty są wielokrotnego użytku. Ten sam egzemplarz specyfikacji, który czyści grupę, może zostać przekazany do skanu weryfikacyjnego, więc sprawdzenie nie może odchodzić od czyszczenia, które ma testować.

Implementacja kroku po kroku potoku sanityzacji

Krok 1 – Wyczyść grupę tożsamości według tagu

Cztery specyfikacje tagów połączone metodą .or(...) obejmują twórcę, edytora, menedżera i firmę. Nic innego się nie przemieszcza, więc Title, Subject i Keywords pozostają dostępne dla indeksu rekordów.

try (Metadata metadata = new Metadata(inputPath)) {
    if (metadata.getFileFormat() == FileFormat.Unknown) return 0;
    int affected = metadata.removeProperties(
            new ContainsTagSpecification(Tags.getPerson().getCreator())
                .or(new ContainsTagSpecification(Tags.getPerson().getEditor()))
                .or(new ContainsTagSpecification(Tags.getPerson().getManager()))
                .or(new ContainsTagSpecification(Tags.getCorporate().getCompany())));
    metadata.save(outputPath);
    return affected;
}

Ochrona FileFormat.Unknown ma większe znaczenie, niż się wydaje. Bez niej nieczytelny plik zwraca zero usunięć, co wywołujący nie może odróżnić od dokumentu, który był czysty od samego początku.

Krok 2 – Wyczyść rodziny pól według nazwy

Wątki komentarzy, liczniki wersji i pola serwera nie mają tagu, więc są dopasowywane po nazwie. Mała podklasa Specification przyjmuje listę podciągów (varargs), co pozwala jednej klasie obsłużyć trzy przejścia:

public class NameContainsSpec extends Specification {
    private final String[] needles;

    public NameContainsSpec(String... needles) {
        this.needles = needles;
    }

    @Override
    public boolean isSatisfiedBy(MetadataProperty candidate) {
        String name = candidate.getName();
        if (name == null) return false;
        for (String n : needles) {
            if (name.contains(n)) return true;
        }
        return false;
    }
}

Linia edycji to grupa, którą zespoły zgodności najbardziej się interesują, ponieważ liczba wersji i data ostatniego wydruku opisują, jak dokument został wyprodukowany:

try (Metadata metadata = new Metadata(inputPath)) {
    if (metadata.getFileFormat() == FileFormat.Unknown) return 0;
    int affected = metadata.removeProperties(new NameContainsSpec(
            "Revision", "TrackedChange", "LastPrinted", "TotalEditingTime", "EditTime"));
    metadata.save(outputPath);
    return affected;
}

Przejście komentarzy i przejście SharePoint to to samo wywołanie z różnymi listami podciągów: Comment, Reviewer, Reviewed dla śladów recenzji oraz Server, Workflow, Approver, ContentType, Template dla pól serwera dokumentów.

Krok 3 – Wyczyść na granicy

Gdy plik opuszcza organizację, selektywność przestaje mieć sens. Jedno wywołanie usuwa każdy pakiet metadanych wykryty przez bibliotekę, w tym niestandardowe części OOXML, których nie obejmuje żaden ukierunkowany predykat:

try (Metadata metadata = new Metadata(inputPath)) {
    if (metadata.getFileFormat() == FileFormat.Unknown) return 0;
    int affected = metadata.sanitize();
    metadata.save(outputPath);
    return affected;
}

Krok 4 – Zweryfikuj i sklasyfikuj to, co pozostało

Skan uruchamia sumę wszystkich reguł przez findProperties i sortuje trafienia do dwóch list. Puste wartości i liczniki równe zero są pomijane, a wpisy, których nazwy zaczynają się od Comment, Revision lub Inspection, są opakowaniami treści, a nie metadanymi:

String value = "";
if (p.getValue() != null && p.getValue().getRawValue() != null) {
    value = String.valueOf(p.getValue().getRawValue());
}
if (value.isEmpty() || value.equals("0") || value.equals("0.0")) continue;
String entry = p.getName() + "=" + value;
String name = p.getName() == null ? "" : p.getName();
if (name.startsWith("Comment") || name.startsWith("Revision")
        || name.startsWith("Inspection")) {
    report.contentLevelLeaks.add(entry);
} else {
    report.metadataLeaks.add(entry);
}

Podział jest tym, co utrzymuje sygnał przejścia/niepowodzenia uczciwym. Wycieki metadanych muszą być puste. Wycieki na poziomie treści pozostają informacyjne, ponieważ komentarze Worda i autorzy śledzonych zmian żyją wewnątrz word/document.xml, a biblioteka metadanych zgłasza je bez edycji; ich usunięcie wymaga biblioteki edytującej treść, takiej jak Aspose.Words.

Kiedy przejście ukierunkowane jest lepsze niż pełna sanityzacja?

Zawsze, gdy dokument nadal jest w użyciu. Plik krążący między recenzentami potrzebuje Title, Subject i Keywords do wyszukiwania i klasyfikacji rekordów, a sanitize() usuwa wszystkie trzy. Uruchom przejścia tożsamości i komentarzy podczas współpracy, zachowaj pola opisowe i zachowaj pełne wyczyszczenie na moment, gdy plik przechodzi granicę do zewnętrznej strony.

Rzeczywisty przepływ pracy: Zadanie eksportu dla zewnętrznego audytora

Wyobraź sobie nocne zadanie. Czyta listę identyfikatorów dokumentów, kopiuje każdy plik do ścieżki tymczasowej, stosuje przejście tożsamości i przejście serwera, wywołuje sanitize() na wszystkim, co jest oznaczone jako opuszczające organizację, a następnie uruchamia kontrolę wycieków na zapisanej kopii. Każdy krok dodaje swoją liczbę zmienionych do jednej linii logu na plik, a niepusta lista wycieków metadanych powoduje niepowodzenie zadania zamiast jedynie ostrzeżenia.

Raz spędziłem popołudnie nad wersją tego zadania, które zgłaszało zero usunięć w 40 plikach i wyglądało na czystą partię. Folder wejściowy zawierał starsze binaria .doc, ochrona formatu zwracała wczesny exit dla każdego z nich i nic w logu nie rozróżniało „nic do usunięcia” od „nic nie zostało odczytane”. Dodanie formatu do logu razem z liczbą naprawiło problem.

Wpływ na biznes: Co to zmienia

Aspekt Ręczna weryfikacja Potok GroupDocs.Metadata
Zasięg pola widoczne w oknie właściwości każdy pakiet wykryty przez bibliotekę, w tym niestandardowe części OOXML
Rejestr pracy notatki, jeśli ktoś je napisał liczba zmienionych na plik i na grupę właściwości
Powtarzalność zależy od osoby wykonującej jedna specyfikacja na regułę, stosowana identycznie do każdego pliku
Weryfikacja otworzyć plik i spojrzeć skan findProperties z dwukierunkową klasyfikacją
Skala jeden plik naraz te same sześć operacji w pętli po folderze eksportu

Inne scenariusze, w których GroupDocs.Metadata się przydaje

Ten sam silnik właściwości odczytuje tak samo dobrze, jak usuwa. Porównywanie metadanych między dwoma wersjami dokumentu pokazuje, co zmieniła runda edycji, co jest przydatne przy sporach o własność i przy wykrywaniu pliku, który został ponownie autorowany poza procesem. Praca z metadata tags zamiast nazw to właśnie to, co czyni oba przypadki przenośnymi pomiędzy DOCX, XLSX, PPTX, PDF i formatami obrazów.

Rozpoczęcie pracy z GroupDocs.Metadata dla Javy

Dodaj repozytorium GroupDocs Java do pom.xml i zależność com.groupdocs:groupdocs-metadata. Biblioteka działa w trybie ewaluacyjnym bez licencji, co wystarcza, aby wykonać wszystkie sześć operacji na przykładowym DOCX i zobaczyć liczby. Zacznij od przejścia tożsamości, dodawaj przejścia rodzin pól w miarę potrzeb źródeł dokumentów i wstaw kontrolę wycieków przed wdrożeniem do produkcji.

Zasoby