# PDF Redaction in C#: Remove Sensitive Data and Sanitize Documents with IronPDF
**Redakcja PDF** w **C# .NET** za pomocą IronPDF trwałe usuwa poufne treści z wewnętrznej struktury dokumentu, nie tylko wizualnie je zakrywając, co uniemożliwia odzyskanie oryginalnych danych poprzez kopiowanie, wyszukiwanie czy analizę kryminalistyczną. To wychodzi daleko poza czarne prostokąty nad tekstem: IronPDF oferuje **redakcję tekstu** z dopasowywaniem wzorców regex, **redakcję opartą na regionach** dla podpisów i obrazów, usuwanie metadanych, **czyszczenie dokumentów** w celu usunięcia osadzonych skryptów oraz skanowanie podatności, dając programistom .NET pełne narzędzia do zgodnego z **HIPAA**, **GDPR** i **PCI DSS** zabezpieczania dokumentów.
*as-heading:2(TL;DR: Przewodnik Quickstart)*
Ten poradnik obejmuje trwałe usuwanie poufnych treści z dokumentów PDF w C# .NET, w tym wzorce tekstowe, obszary obrazów, metadane i osadzone skrypty.
- **Kto to jest:** Programiści .NET zajmujący się poufnymi dokumentami w branży medycznej, prawnej, finansowej lub rządowej.
- **Co zbudujesz:** Redakcja tekstu z dopasowywaniem wzorców regex (SSN, karty kredytowe, e-maile), redakcja obszarów oparta na współrzędnych dla podpisów i zdjęć, czyszczenie metadanych, czyszczenie PDF w celu usunięcia osadzonych skryptów oraz skanowanie podatności oparte na YARA.
- **Gdzie działa:** .NET 10, .NET 8 LTS, .NET Framework 4.6.2+ i .NET Standard 2.0. Wszystkie operacje działają lokalnie, bez zewnętrznych zależności.
- **Kiedy używać tego podejścia:** Gdy musisz udostępnić dokumenty w celu odkrywania prawnego, na potrzeby wniosków FOIA lub dystrybucji zewnętrznej, zapewniając, że usunięta treść jest naprawdę usunięta.
- **Dlaczego to ma znaczenie technicznie:** Nakładki wizualne pozostawiają oryginalny tekst odzyskiwalnym w strumieniach treści PDF. Redakcja IronPDF usuwa dane znakowe z samej struktury dokumentu, co uniemożliwia ich odzyskanie.
Redagowanie poufnego tekstu z PDF za pomocą kilku linii kodu:
```cs
:title=Redact Sensitive Text with IronPDF
using IronPdf;
PdfDocument pdf = PdfDocument.FromFile("confidential-report.pdf");
pdf.RedactTextOnAllPages("CONFIDENTIAL");
pdf.SaveAs("redacted-report.pdf");
```
Po zakupie lub zapisaniu się na 30-dniowy okres próbny IronPDF, dodaj swój klucz licencyjny na początku aplikacji.
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp-2.cs
```
!!!--LIBRARY_START_TRIAL_BLOCK--!!!
!!!--LIBRARY_NUGET_INSTALL_BLOCK--!!!
*as-heading:2(Spis treści)*
- **TL;DR: Przewodnik Szybkiego Startu**
- [Krótki Przegląd](#anchor-tldr-quickstart-guide)
- **Redagowanie tekstu z dokumentów PDF**
- [Jaka jest różnica między prawdziwą redakcją a wizualnym nakładką?](#anchor-true-redaction-vs-overlay)
- [Jak zredagować tekst na wszystkich stronach w dokumencie PDF?](#anchor-redact-text-all-pages)
- [Jak mogę zredagować tekst tylko na określonych stronach?](#anchor-redact-specific-pages)
- [Jak dostosować wygląd zredagowanej treści?](#anchor-customize-redaction-appearance)
- **Dopasowywanie wzorców i automatyczna redakcja**
- [Jak mogę użyć wyrażeń regularnych, żeby znaleźć i zredagować poufne wzorce?](#anchor-regex-pattern-redaction)
- [Jak zbudować możliwy do ponownego użycia skaner danych poufnych?](#anchor-sensitive-data-scanner)
- **Redakcja oparta na regionach**
- [Jak mogę zredagować określone regiony lub obszary w PDF?](#anchor-redact-regions)
- [Jak mogę zredagować wiele regionów na różnych stronach?](#anchor-multiple-regions)
- **Usuwanie danych poufnych z metadanych PDF**
- [Jak usunąć metadane, które mogłyby ujawnić poufne informacje?](#anchor-remove-metadata)
- **Sanityzacja PDF w .NET**
- [Jak mogę zsanityzować PDF w celu usunięcia osadzonych skryptów i ukrytych zagrożeń?](#anchor-sanitize-pdf)
- [Jak zeskanować PDF w poszukiwaniu podatności bezpieczeństwa?](#anchor-scan-vulnerabilities)
- **Kompletne przepływy pracy**
- [Jak mogę zbudować kompletny przepływ redakcji i sanitacji?](#anchor-complete-pipeline)
- [Następne kroki](#anchor-next-steps)
<a id="anchor-true-redaction-vs-overlay"></a>
## Jaka jest różnica między prawdziwą redakcją a wizualnym nakładką?
Zrozumienie różnicy między prawdziwą redakcją a wizualną nakładką jest kluczowe dla każdego zajmującego się poufnymi dokumentami. Wiele narzędzi i metod manualnych tworzy wrażenie redakcji bez faktycznego usunięcia danych źródłowych. To fałszywe poczucie bezpieczeństwa spowodowało liczne głośne naruszenia danych i niepowodzenia w zakresie zgodności.
Podejścia wizualne typowo rysują nieprzejrzyste kształty nad wrażliwą treścią. Tekst pozostaje w pełni nienaruszony w strukturze PDF. Ktoś oglądający dokument widzi czarny prostokąt, ale oryginalne znaki wciąż istnieją w strumieniach treści pliku. Wybór całego tekstu na stronie, użycie narzędzi dostępności czy badanie surowych danych PDF ujawni wszystko, co miało być ukryte. Sprawy sądowe zostały skompromitowane, gdy zredagowane zgłoszenia zostały łatwo odredagowane przez stronę przeciwna. Agencje rządowe przypadkowo ujawniły informacje oznaczone jako tajne, które wydawały się ukryte, ale były w pełni odzyskiwalne.
Prawdziwa redakcja działa inaczej. Gdy używasz metod redakcji IronPDF, biblioteka lokalizuje określony tekst w wewnętrznej strukturze PDF i całkowicie go usuwa. Dane znakowe są usuwane z strumieni treści. Reprezentacja wizualna jest zastępowana przez znak redakcji, zazwyczaj czarny prostokąt, ale oryginalna treść już nigdzie nie istnieje w pliku. Żadne zaznaczenia, kopiowanie ani analiza kryminalistyczna nie mogą odzyskać tego, co zostało trwałe usunięte.
IronPDF implementuje prawdziwą redakcję poprzez modyfikację PDF na poziomie strukturalnym. Metoda `RedactTextOnAllPages` i jej odmiany przeszukują treść strony, identyfikują dopasowany tekst, usuwają go z modelu obiektu dokumentu i opcjonalnie rysują wizualny wskaźnik tam, gdzie ta treść się znajdowała. To podejście jest zgodne z wytycznymi organizacji takich jak NIST dotyczących bezpiecznej redakcji dokumentów.
Praktyczne konsekwencje są znaczące. Jeśli musisz udostępniać dokumenty zewnętrznie, zgłaszać pliki do odkrywania prawnego, publikować zasoby w ramach wniosków o dostęp do informacji lub dystrybuować raporty, chroniąc dane umożliwiające identyfikację osobistą, tylko prawdziwa redakcja zapewnia odpowiednią ochronę. Wizualne nakładki mogą wystarczyć na wewnętrzne wersje robocze, gdy po prostu chcesz odwrócić uwagę od pewnych sekcji, ale nigdy nie powinno się im ufać w kontekście rzeczywistej ochrony danych. Dla dodatkowych środków bezpieczeństwa dokumentów zobacz nasze przewodniki dotyczące [szyfrowania PDF](/tutorials/encrypt-pdf-csharp/) i [podpisów cyfrowych](/tutorials/pdf-digital-signatures-csharp-guide/).
---
## How do I Redact PDF Text in C# Across an Entire Document?
<a id="anchor-redact-text-all-pages"></a>
Najczęstszy scenariusz redakcji obejmuje usunięcie wszystkich wystąpień konkretnego tekstu w całym dokumencie. Być może musisz usunąć czyjeś imię z raportu, numery kont z oświadczeń finansowych lub wewnętrzne kody referencyjne przed dystrybucją zewnętrzną. IronPDF ułatwia to dzięki metodzie `RedactTextOnAllPages`.
#### Wejscie
Dokument rejestrów pracowniczych zawierający informacje osobiste, w tym imiona, numery ubezpieczenia społecznego i identyfikatory pracowników.
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/02-employee-records-before.pdf" width="100%" height="400px">
</iframe>
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-text-all-pages.cs
```
Ten kod ładuje PDF zawierający informacje o pracowniku i usuwa trzy fragmenty poufnych danych, wywołując `RedactTextOnAllPages` dla każdej wartości. Każde wywołanie przeszukuje każdą stronę dokumentu i trwałe usuwa wszystkie pasujące przypadki imienia pracownika, numeru ubezpieczenia społecznego i wewnętrznego identyfikatora.
#### Przykładowy Wynik
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/02-employee-records-after.pdf" width="100%" height="400px">
</iframe>
Domyślne zachowanie rysuje czarne prostokąty, gdzie pojawiał się zredagowany tekst, i zastępuje rzeczywiste znaki gwiazdkami w strukturze dokumentu. Zapewnia to zarówno wizualne potwierdzenie, że redakcja miała miejsce, jak i gwarantuje, że oryginalna treść została całkowicie usunięta.
W przypadku pracy z dłuższymi dokumentami lub wieloma celami redakcji można efektywnie łączyć te wywołania:
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-text-list.cs
```
Ten wzorzec sprawdza się dobrze, gdy dysponujesz znaną listą wrażliwych wartości, które należy usunąć. Dokument jest ładowany jednokrotnie, wszystkie zmiany są wprowadzane w pamięci, a ostateczny wynik jest zapisywany. Każdy termin jest przetwarzany niezależnie, więc częściowe dopasowania lub różnice w formatowaniu między terminami nie mają wpływu na inne tłumaczenia.
<a id="anchor-redact-specific-pages"></a>
## Jak mogę zredagować tekst tylko na określonych stronach?
Czasami potrzebna jest bardziej precyzyjna kontrola nad miejscami, w których występują redakcje. Dokument może zawierać stronę tytułową z informacjami, które powinny pozostać niezmienione, lub może być wiadomo, że dane poufne pojawiają się tylko w niektórych sekcjach. IronPDF oferuje `RedactTextOnPage` dla pojedynczej strony i `RedactTextOnPages` dla wycelowania w wiele określonych stron.
#### Wejscie
Wielostronicowy pakiet umów z nazwami klientów na stronie podpisowej oraz warunkami finansowymi umieszczonymi na określonych stronach w całym dokumencie.
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/03-contract-bundle-before.pdf" width="100%" height="400px">
</iframe>
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-specific-pages.cs
```
Ten kod demonstruje selektywną redakcję, używając `RedactTextOnPage` dla pojedynczej strony i `RedactTextOnPages` dla wielu określonych stron. Nazwa klienta została usunięta tylko ze strony 1 (indeks 0), natomiast warunki płatności zostały usunięte ze stron 3, 5 i 7 (indeksy 2, 4, 6), pozostawiając pozostałe strony bez zmian.
#### Przykładowy Wynik
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/03-contract-bundle-after.pdf" width="100%" height="400px">
</iframe>
Indeksy stron w IronPDF są zerowe, co oznacza, że pierwsza strona ma indeks 0, druga 1 i tak dalej. Jest to zgodne ze standardowymi konwencjami programistycznymi i odpowiada sposobowi, w jaki większość programistów postrzega dostęp do tablic.
Skierowanie na konkretne strony poprawia wydajność podczas przetwarzania dużych dokumentów. Zamiast przeszukiwać setki stron w poszukiwaniu tekstu, który pojawia się tylko w kilku miejscach, możesz wskazać silnikowi redakcyjnemu dokładnie, gdzie ma szukać. Ma to znaczenie w scenariuszach przetwarzania wsadowego, w których może być przetwarzanych tysiące dokumentów. Aby uzyskać maksymalną przepustowość, warto rozważyć zastosowanie technik [asynchronicznych i wielowątkowych](/how-to/async/).
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-large-document.cs
```
To ukierunkowane podejście przetwarza tylko odpowiednie sekcje 500-stronicowego dokumentu, znacznie skracając czas wykonania w porównaniu do skanowania każdej strony dla każdego terminu redakcyjnego.
<a id="anchor-customize-redaction-appearance"></a>
## Jak dostosować wygląd zredagowanej treści?
IronPDF oferuje kilka parametrów pozwalających kontrolować sposób wyświetlania redakcji w ostatecznej wersji dokumentu. Można dostosować wrażliwość na wielkość liter, dopasowanie całych słów, wyświetlanie prostokątów oraz tekst zastępczy wyświetlany w miejscu usuniętej treści.
#### Wejscie
Dokument prawny zawierający różne wrażliwe terminy, w tym oznaczenia klasyfikacyjne, hasła i wewnętrzne kody referencyjne, które wymagają różnych metod redagowania.
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/04-legal-brief-before.pdf" width="100%" height="400px">
</iframe>
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/customize-redaction-appearance.cs
```
Ten kod pokazuje cztery różne konfiguracje redakcji, używając opcjonalnych parametrów `RedactTextOnAllPages`. Pokazuje dopasowanie dokładne z uwzględnieniem wielkości liter z zastąpieniem "[REDACTED]", dopasowanie bez uwzględnienia wielkości liter z gwiazdkami, dopasowanie częściowe słów w celu wychwycenia odmian takich jak "hasła" oraz niewidoczne usuwanie bez wizualnych prostokątów w celu płynnej eliminacji treści.
#### Przykładowy Wynik
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/04-legal-brief-after.pdf" width="100%" height="400px">
</iframe>
Parametry służą różnym celom w zależności od wymagań:
`CaseSensitive` określa, czy dopasowanie uwzględnia wielkość liter. Dokumenty prawne często używają specyficznych kapitalizacji, które mają konkretne znaczenie, dlatego porównanie uwzględniające wielkość liter zapewnia, że usuwasz tylko dokładne dopasowania. Przetwarzanie ogólnego tekstu, gdzie wielkość liter może się różnić, może wymagać porównania bez względu na wielkość liter, aby uchwycić wszystkie przypadki.
`OnlyMatchWholeWords` kontroluje, czy wyszukiwanie pasuje do całych słów czy częściowych ciągów. Podczas redagowania nazw zazwyczaj pożądane jest dopasowanie całych słów, tak aby "Smith" nie spowodowało przypadkowego usunięcia części słowa "Blacksmith" lub "Smithfield". Podczas redagowania wzorców, takich jak prefiksy numerów kont, może być konieczne stosowanie dopasowania częściowego w celu wychwycenia różnych wariantów.
`DrawRectangles` określa, czy czarne prostokąty pojawiają się tam, gdzie usunięto treść. Większość kontekstów regulacyjnych i prawnych wymaga widocznych znaków redakcyjnych jako dowodu, że treść została celowo usunięta, a nie przypadkowo pominięta. Wewnętrzne procesy robocze mogą preferować niewidoczne usunięcie w celu uzyskania bardziej przejrzystego wyniku.
`ReplacementText` definiuje, jakie znaki pojawiają się zamiast zredagowanej treści. Typowe rozwiązania to gwiazdki, oznaczenia "REDACTED" lub puste ciągi znaków. Tekst zastępczy pojawia się w strukturze dokumentu, jeśli ktoś spróbuje zaznaczyć lub skopiować fragment z zacenzurowanego obszaru.
---
<a id="anchor-regex-pattern-redaction"></a>
## Jak mogę używać wyrażeń regularnych do wyszukiwania i redagowania wrażliwych wzorców?
Redagowanie znanych ciągów tekstowych sprawdza się, gdy masz konkretne wartości do usunięcia, ale wiele typów danych poufnych ma raczej przewidywalne wzorce niż stałe wartości. Numery ubezpieczenia społecznego, numery kart kredytowych, adresy e-mail, numery telefonów i daty mają rozpoznawalne formaty, które można dopasować za pomocą wyrażeń regularnych. Budowa systemu redakcji opartego na wzorach umożliwia usunięcie prywatnych informacji z treści PDF bez znajomości każdej konkretnej wartości z góry.
[Możliwości](/how-to/extract-text-and-images/) IronPDF w[ ](/how-to/extract-text-and-images/)zakresie [ekstrakcji tekstu](/how-to/extract-text-and-images/) w połączeniu z metodami redagowania umożliwiają tworzenie wydajnych procesów dopasowywania wzorców. Wyodrębniasz tekst, identyfikujesz dopasowania za pomocą wyrażeń regularnych .NET, a następnie redagujesz każdą wykrytą wartość.
```cs
using IronPdf;
using System.Text.RegularExpressions;
using System.Collections.Generic;
public class PatternRedactor
{
// Common patterns for sensitive data
private static readonly Dictionary<string, string> SensitivePatterns = new Dictionary<string, string>
{
// US Social Security Number: 123-45-6789
{ "SSN", @"\b\d{3}-\d{2}-\d{4}\b" },
// Credit Card Numbers: various formats with 13-19 digits
{ "CreditCard", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
// Email Addresses
{ "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
// US Phone Numbers: (123) 456-7890 or 123-456-7890
{ "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" },
// Dates: MM/DD/YYYY or MM-DD-YYYY
{ "Date", @"\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" },
// IP Addresses
{ "IPAddress", @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b" }
};
public void RedactPatterns(string inputPath, string outputPath, params string[] patternNames)
{
// Load the PDF
PdfDocument pdf = PdfDocument.FromFile(inputPath);
// Extract all text from the document
string fullText = pdf.ExtractAllText();
// Track unique matches to avoid duplicate redaction attempts
HashSet<string> matchesToRedact = new HashSet<string>();
// Find all matches for requested patterns
foreach (string patternName in patternNames)
{
if (SensitivePatterns.TryGetValue(patternName, out string pattern))
{
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(fullText);
foreach (Match match in matches)
{
matchesToRedact.Add(match.Value);
}
}
}
// Redact each unique match
foreach (string sensitiveValue in matchesToRedact)
{
pdf.RedactTextOnAllPages(sensitiveValue);
}
// Save the redacted document
pdf.SaveAs(outputPath);
}
}
// Usage example
class Program
{
static void Main()
{
PatternRedactor redactor = new PatternRedactor();
// Redact SSNs and credit cards from a financial document
redactor.RedactPatterns(
"customer-data.pdf",
"customer-data-safe.pdf",
"SSN", "CreditCard", "Email"
);
}
}
```
To podejście oparte na wzorach dobrze się skaluje, ponieważ definiujesz wzory raz i stosujesz je do dowolnego dokumentu. Dodanie nowych typów danych wymaga jedynie dodania nowych wzorców wyrażeń regularnych do słownika.
<a id="anchor-sensitive-data-scanner"></a>
## Jak zbudować skaner danych wrażliwych, który można ponownie wykorzystać?
W środowiskach produkcyjnych często trzeba skanować dokumenty i zgłaszać, jakie informacje poufne się w nich znajdują, zanim zdecyduje się na ich redagowanie. Pomaga to w audycie zgodności i umożliwia weryfikację decyzji dotyczących redakcji przez człowieka. Poniższa klasa oferuje funkcje skanowania oraz redagowania.
```cs
using IronPdf;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Linq;
public class SensitiveDataMatch
{
public string PatternType { get; set; }
public string Value { get; set; }
public int PageNumber { get; set; }
}
public class ScanResult
{
public string FilePath { get; set; }
public List<SensitiveDataMatch> Matches { get; set; } = new List<SensitiveDataMatch>();
public bool ContainsSensitiveData => Matches.Count > 0;
public Dictionary<string, int> GetSummary()
{
return Matches.GroupBy(m => m.PatternType)
.ToDictionary(g => g.Key, g => g.Count());
}
}
public class DocumentScanner
{
private readonly Dictionary<string, string> _patterns;
public DocumentScanner()
{
_patterns = new Dictionary<string, string>
{
{ "Social Security Number", @"\b\d{3}-\d{2}-\d{4}\b" },
{ "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
{ "Email Address", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
{ "Phone Number", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" },
{ "Date of Birth Pattern", @"\b(?:DOB|Date of Birth|Birth Date)[:\s]+\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" }
};
}
public ScanResult ScanDocument(string filePath)
{
ScanResult result = new ScanResult { FilePath = filePath };
PdfDocument pdf = PdfDocument.FromFile(filePath);
// Scan each page individually to track location
for (int pageIndex = 0; pageIndex < pdf.PageCount; pageIndex++)
{
string pageText = pdf.ExtractTextFromPage(pageIndex);
foreach (var pattern in _patterns)
{
Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(pageText);
foreach (Match match in matches)
{
result.Matches.Add(new SensitiveDataMatch
{
PatternType = pattern.Key,
Value = MaskValue(match.Value, pattern.Key),
PageNumber = pageIndex + 1
});
}
}
}
return result;
}
// Partially mask values for safe storage
private string MaskValue(string value, string patternType)
{
if (patternType == "Social Security Number" && value.Length >= 4)
{
return "XXX-XX-" + value.Substring(value.Length - 4);
}
if (patternType == "Credit Card" && value.Length >= 4)
{
return "****-****-****-" + value.Substring(value.Length - 4);
}
if (patternType == "Email Address")
{
int atIndex = value.IndexOf('@');
if (atIndex > 2)
{
return value.Substring(0, 2) + "***" + value.Substring(atIndex);
}
}
return value.Length > 4 ? value.Substring(0, 2) + "***" : "****";
}
public void ScanAndRedact(string inputPath, string outputPath)
{
// First scan to identify sensitive data
ScanResult scanResult = ScanDocument(inputPath);
if (!scanResult.ContainsSensitiveData)
{
return;
}
// Load document for redaction
PdfDocument pdf = PdfDocument.FromFile(inputPath);
// Extract unique actual values (not masked) for redaction
string fullText = pdf.ExtractAllText();
HashSet<string> valuesToRedact = new HashSet<string>();
foreach (var pattern in _patterns)
{
Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
foreach (Match match in regex.Matches(fullText))
{
valuesToRedact.Add(match.Value);
}
}
// Apply redactions
foreach (string value in valuesToRedact)
{
pdf.RedactTextOnAllPages(value);
}
pdf.SaveAs(outputPath);
}
}
// Usage
class Program
{
static void Main()
{
DocumentScanner scanner = new DocumentScanner();
// Scan only (for audit purposes)
ScanResult result = scanner.ScanDocument("application-form.pdf");
var summary = result.GetSummary();
// Scan and redact in one operation
scanner.ScanAndRedact("application-form.pdf", "application-form-redacted.pdf");
}
}
```
Skaner zapewnia wgląd w to, jakie informacje poufne istnieją, zanim nastąpią jakiekolwiek modyfikacje. Wspiera to procesy zapewniania zgodności, w których wymagana jest dokumentacja tego, co zostało znalezione i usunięte. Funkcja maskowania gwarantuje, że pliki dziennika i raporty same w sobie nie staną się źródłem ujawnienia danych.
---
<a id="anchor-redact-regions"></a>
## Jak zamazać określone obszary w pliku PDF?
Cenzurowanie tekstu skutecznie odnosi się do treści opartej na znakach, ale PDF-y często zawierają poufne informacje w formach, które dopasowanie tekstu nie może obsłużyć. Podpisy, zdjęcia, odręczne adnotacje, pieczątki i elementy graficzne wymagają innego podejścia. Redakcja oparta na regionach pozwala określić prostokątne obszary przez ich współrzędne i trwale zaciemnić wszystko w ich granicach.
IronPDF używa struktury `RectangleF` do definiowania regionów redagowania. Należy określić współrzędne X i Y lewego górnego rogu, a następnie szerokość i wysokość obszaru. Współrzędne są mierzone w punktach od lewego dolnego rogu strony, co odpowiada układowi współrzędnych specyfikacji PDF.
#### Wejscie
Podpisany dokument umowy zawierający odręczne podpisy oraz zdjęcie dokumentu tożsamości, które należy zamazać przy użyciu funkcji zamazywania obszarów na podstawie współrzędnych.
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/06-signed-agreement-before.pdf" width="100%" height="400px">
</iframe>
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-region-basic.cs
```
Ten kod używa struktur `RectangleF` do definiowania prostokątnych obszarów do redagowania. Obszar podpisu znajduje się we współrzędnych (100, 650) i ma wymiary 200 x 50 pikseli, natomiast obszar zdjęcia znajduje się we współrzędnych (450, 700) i ma wymiary 100 x 120 pikseli. Metoda `RedactRegionsOnAllPages` stosuje czarne prostokąty nad tymi regionami na wszystkich stronach.
#### Przykładowy Wynik
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/06-signed-agreement-after.pdf" width="100%" height="400px">
</iframe>
Określenie prawidłowych współrzędnych często wymaga pewnych eksperymentów lub pomiarów. Strony PDF zazwyczaj wykorzystują układ współrzędnych, w którym jeden punkt odpowiada 1/72 cała. Standardowa strona formatu US Letter ma szerokość 612 punktów i wysokość 792 punktów. Strony formatu A4 mają wymiary około 595 na 842 punktów. Pomocne mogą być narzędzia do przeglądania plików PDF, które wyświetlają współrzędne podczas przesuwania kursora, lub można programowo wyodrębnić wymiary strony:
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-region-dimensions.cs
```
<a id="anchor-multiple-regions"></a>
## Jak mogę zredagować wiele obszarów na różnych stronach?
Złożone dokumenty często wymagają usunięcia różnych fragmentów na różnych stronach. Formularz wielostronicowy może zawierać linie podpisu w różnych pozycjach, a różne strony mogą zawierać zdjęcia, pieczęcie lub inne elementy graficzne w unikalnych miejscach. IronPDF zawiera metody specyficzne dla stron do ukierunkowanej redakcji regionów.
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-multiple-regions.cs
```
Dokumenty o spójnym układzie korzystają z definicji regionów wielokrotnego użytku:
```cs
using IronPdf;
using IronSoftware.Drawing;
public class FormRegions
{
// Standard form regions based on common templates
public static RectangleF HeaderLogo => new RectangleF(20, 720, 150, 60);
public static RectangleF SignatureBlock => new RectangleF(72, 72, 200, 50);
public static RectangleF DateField => new RectangleF(400, 72, 120, 20);
public static RectangleF PhotoId => new RectangleF(480, 650, 100, 130);
public static RectangleF AddressBlock => new RectangleF(72, 600, 250, 80);
}
class Program
{
static void Main()
{
PdfDocument pdf = PdfDocument.FromFile("standard-form.pdf");
// Apply standard redactions using predefined regions
pdf.RedactRegionsOnAllPages(FormRegions.SignatureBlock);
pdf.RedactRegionsOnAllPages(FormRegions.DateField);
pdf.RedactRegionOnPage(0, FormRegions.PhotoId);
pdf.SaveAs("standard-form-redacted.pdf");
}
}
```
---
<a id="anchor-remove-metadata"></a>
## Jak usunąć metadane, które mogą ujawnić poufne informacje?
Metadane plików PDF stanowią często pomijane źródło wycieku informacji. Każdy plik PDF zawiera właściwości, które mogą ujawniać poufne informacje: nazwisko autora i nazwę użytkownika, oprogramowanie użyte do utworzenia dokumentu, znaczniki czasu utworzenia i modyfikacji, oryginalną nazwę pliku, historię zmian oraz właściwości niestandardowe dodane przez różne aplikacje. Przed udostępnieniem dokumentów na zewnątrz konieczne jest usunięcie lub oczyszczenie tych metadanych. Aby uzyskać kompleksowy przegląd operacji związanych z metadanymi, zapoznaj się z naszym [przewodnikiem dotyczącym metadanych](/how-to/metadata/).
IronPDF ujawnia metadane dokumentu poprzez właściwość `MetaData`, pozwalającą na odczytywanie, modyfikowanie lub całkowite usuwanie istniejących wartości.
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/view-metadata.cs
```
Aby usunąć wrażliwe metadane przed dystrybucją:
#### Wejscie
Wewnętrzna notatka zawierająca osadzone metadane, takie jak nazwiska autorów, znaczniki czasu utworzenia oraz niestandardowe właściwości, które mogą ujawniać poufne informacje organizacyjne.
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/07-internal-report-before.pdf" width="100%" height="400px">
</iframe>
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/remove-metadata.cs
```
Ten kod zastępuje identyfikujące pola metadanych wartościami ogólnymi, normalizuje znaczniki czasu do bieżącej daty oraz usuwa niestandardowe klucze metadanych, które mogły zostać dodane przez aplikacje. Metoda `RemoveMetaDataKey` celuje w określone właściwości jak "OryginalnaNazwaPliku" i "OstatnioZapisanePrzez", które mogą ujawniać wewnętrzne informacje.
#### Przykładowy Wynik
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/07-internal-report-after.pdf" width="100%" height="400px">
</iframe>
Dokładne czyszczenie metadanych w operacjach wsadowych wymaga systematycznego podejścia:
```cs
using IronPdf;
using System;
using System.Collections.Generic;
public class MetadataCleaner
{
private readonly string _defaultAuthor;
private readonly string _defaultCreator;
public MetadataCleaner(string organizationName)
{
_defaultAuthor = organizationName;
_defaultCreator = $"{organizationName} Document System";
}
public void CleanMetadata(PdfDocument pdf)
{
// Replace standard metadata fields
pdf.MetaData.Author = _defaultAuthor;
pdf.MetaData.Creator = _defaultCreator;
pdf.MetaData.Producer = "";
pdf.MetaData.Subject = "";
pdf.MetaData.Keywords = "";
// Normalize timestamps
DateTime now = DateTime.Now;
pdf.MetaData.CreationDate = now;
pdf.MetaData.ModifiedDate = now;
// Get all keys and remove potentially sensitive ones
List<string> keysToRemove = new List<string>();
foreach (string key in pdf.MetaData.Keys())
{
// Keep only essential keys
if (!IsEssentialKey(key))
{
keysToRemove.Add(key);
}
}
foreach (string key in keysToRemove)
{
pdf.MetaData.RemoveMetaDataKey(key);
}
}
private bool IsEssentialKey(string key)
{
// Keep only the basic display properties
string[] essentialKeys = { "Title", "Author", "CreationDate", "ModifiedDate" };
foreach (string essential in essentialKeys)
{
if (key.Equals(essential, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
}
// Usage
class Program
{
static void Main()
{
MetadataCleaner cleaner = new MetadataCleaner("Acme Corporation");
PdfDocument pdf = PdfDocument.FromFile("report.pdf");
cleaner.CleanMetadata(pdf);
pdf.SaveAs("report-clean.pdf");
}
}
```
---
<a id="anchor-sanitize-pdf"></a>
## Jak mogę oczyścić plik PDF, aby usunąć osadzone skrypty i ukryte zagrożenia?
Oczyszczanie plików PDF rozwiązuje problemy związane z bezpieczeństwem, które wykraczają poza widoczną treść i metadane. Pliki PDF mogą zawierać kod JavaScript, osadzone pliki wykonywalne, akcje formularzy wywołujące połączenia zewnętrzne oraz inne potencjalnie złośliwe elementy. Funkcje te służą uzasadnionym celom, takim jak formularze interaktywne i treści multimedialne, ale stwarzają również wektory ataku. Oczyszczanie pliku PDF usuwa te aktywne elementy, zachowując jednocześnie zawartość wizualną. Aby uzyskać dodatkowe informacje na temat metod czyszczenia danych, zapoznaj się z naszym [przewodnikiem "Jak oczyścić plik PDF](/how-to/sanitize-pdf/)".
Klasa `Cleaner` IronPDF obsługuje zależność poprzez eleganckie podejście: przekonwertowanie PDF na format obrazu, a następnie z powrotem. Proces ten usuwa kod JavaScript, osadzone obiekty, akcje formularzy i adnotacje, zachowując jednocześnie nienaruszony wygląd strony. Biblioteka oferuje dwie metody oczyszczania o różnych właściwościach.
#### Wejscie
Dokument PDF otrzymany z zewnętrznego źródła, który może zawierać JavaScript, osadzone obiekty lub inne potencjalnie złośliwe treści aktywne.
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/08-received-document-before.pdf" width="100%" height="400px">
</iframe>
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/sanitize-pdf.cs
```
Ten kod pokazuje dwie metody zależności dostarczane przez klasę `Cleaner` IronPDF. `SanitizeWithSvg` konwertuje PDF przez pośredni format SVG, zachowując tekst do wyszukiwania, usuwając jednocześnie aktywną treść. `SanitizeWithBitmap` najpierw konwertuje strony na obrazy, produkując dokładne wizualne kopie, ale z tekstem renderowanym jako niewyszukiwalne grafiki.
#### Przykładowy Wynik
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/08-received-document-after.pdf" width="100%" height="400px">
</iframe>
Metoda SVG działa szybciej i zachowuje tekst jako treść, którą można przeszukiwać, dzięki czemu nadaje się do dokumentów, które muszą pozostać zindeksowane lub dostępne. Metoda bitmapowa tworzy dokładne kopie wizualne, ale konwertuje tekst na obrazy, co uniemożliwia zaznaczanie i wyszukiwanie tekstu. Wybierz opcję zgodnie z wymaganiami dotyczącymi dokumentu docelowego.
Można również zastosować opcje renderowania podczas czyszczenia danych, aby dostosować wynik:
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/sanitize-with-options.cs
```
Srodowiska o wysokim poziomie bezpieczeństwa często wymagają łączenia sanitacji z innymi środkami ochronnymi:
```cs
using IronPdf;
using System;
public class SecureDocumentProcessor
{
public PdfDocument ProcessUntrustedDocument(string inputPath)
{
// Load the document
PdfDocument original = PdfDocument.FromFile(inputPath);
// Step 1: Sanitize to remove active content
PdfDocument sanitized = Cleaner.SanitizeWithSvg(original);
// Step 2: Clean metadata
sanitized.MetaData.Author = "Processed Document";
sanitized.MetaData.Creator = "Secure Processor";
sanitized.MetaData.Producer = "";
sanitized.MetaData.CreationDate = DateTime.Now;
sanitized.MetaData.ModifiedDate = DateTime.Now;
// Remove all custom metadata
foreach (string key in sanitized.MetaData.Keys())
{
if (key != "Title" && key != "Author" && key != "CreationDate" && key != "ModifiedDate")
{
sanitized.MetaData.RemoveMetaDataKey(key);
}
}
return sanitized;
}
}
// Usage
class Program
{
static void Main()
{
SecureDocumentProcessor processor = new SecureDocumentProcessor();
PdfDocument safe = processor.ProcessUntrustedDocument("email-attachment.pdf");
safe.SaveAs("email-attachment-safe.pdf");
}
}
```
<a id="anchor-scan-vulnerabilities"></a>
## Jak przeskanować plik PDF pod kątem luk w zabezpieczeniach?
Przed przetworzeniem lub oczyszczeniem dokumentów warto ocenić, jakie potencjalne zagrożenia zawierają. Metoda `Cleaner.ScanPdf` IronPDF bada dokumenty przy użyciu reguł YARA, które są definicjami wzorców często używanymi w analizie złośliwego oprogramowania i wykrywaniu zagrożeń. Skanowanie identyfikuje cechy charakterystyczne dla złośliwych plików PDF.
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/scan-vulnerabilities.cs
```
Można dostarczyć niestandardowe pliki reguł YARA w celu spełnienia specjalistycznych wymagań dotyczących wykrywania. Organizacje o specyficznych modelach zagrożeń lub wymaganiach dotyczących zgodności często utrzymują własne zestawy reguł ukierunkowane na konkretne wzorce podatności.
```cs
:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/scan-custom-yara.cs
```
Włączenie skanowania do procesów przyjmowania dokumentów pomaga zautomatyzować decyzje dotyczące bezpieczeństwa:
```cs
using IronPdf;
using System;
using System.IO;
public enum DocumentSafetyLevel
{
Safe,
Suspicious,
Dangerous
}
public class DocumentSecurityGateway
{
public DocumentSafetyLevel EvaluateDocument(string filePath)
{
PdfDocument pdf = PdfDocument.FromFile(filePath);
CleanerScanResult scan = Cleaner.ScanPdf(pdf);
if (!scan.IsDetected)
{
return DocumentSafetyLevel.Safe;
}
// Evaluate severity based on number of risks
if (scan.Risks.Count > 5)
{
return DocumentSafetyLevel.Dangerous;
}
return DocumentSafetyLevel.Suspicious;
}
public PdfDocument ProcessIncomingDocument(string filePath, string outputDirectory)
{
DocumentSafetyLevel safety = EvaluateDocument(filePath);
string fileName = Path.GetFileName(filePath);
switch (safety)
{
case DocumentSafetyLevel.Safe:
return PdfDocument.FromFile(filePath);
case DocumentSafetyLevel.Suspicious:
PdfDocument suspicious = PdfDocument.FromFile(filePath);
return Cleaner.SanitizeWithSvg(suspicious);
case DocumentSafetyLevel.Dangerous:
throw new SecurityException($"Document {fileName} contains dangerous content");
default:
throw new InvalidOperationException("Unknown safety level");
}
}
}
```
---
<a id="anchor-complete-pipeline"></a>
## Jak zbudować kompletny proces redagowania i czyszczenia danych?
Przetwarzanie dokumentów produkcyjnych zazwyczaj wymaga połączenia wielu technik zabezpieczeń w spójny proces. Kompletny proces może obejmować skanowanie przychodzących dokumentów pod kątem zagrożeń, oczyszczanie tych, które przeszły wstępną kontrolę, cenzurowanie tekstu i określonych obszarów, usuwanie metadanych oraz tworzenie dzienników audytowych dokumentujących wszystkie podjęte działania. Ten przykład ilustruje takie zintegrowane podejście.
```cs
using IronPdf;
using IronSoftware.Drawing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
public class DocumentProcessingResult
{
public string OriginalFile { get; set; }
public string OutputFile { get; set; }
public bool WasSanitized { get; set; }
public int TextRedactionsApplied { get; set; }
public int RegionRedactionsApplied { get; set; }
public bool MetadataCleaned { get; set; }
public List<string> SensitiveDataTypesFound { get; set; } = new List<string>();
public DateTime ProcessedAt { get; set; }
public bool Success { get; set; }
public string ErrorMessage { get; set; }
}
public class ComprehensiveDocumentProcessor
{
// Sensitive data patterns
private readonly Dictionary<string, string> _sensitivePatterns = new Dictionary<string, string>
{
{ "SSN", @"\b\d{3}-\d{2}-\d{4}\b" },
{ "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
{ "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
{ "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" }
};
// Standard regions to redact (signature areas, photo locations)
private readonly List<RectangleF> _standardRedactionRegions = new List<RectangleF>
{
new RectangleF(72, 72, 200, 50), // Bottom left signature
new RectangleF(350, 72, 200, 50) // Bottom right signature
};
private readonly string _organizationName;
public ComprehensiveDocumentProcessor(string organizationName)
{
_organizationName = organizationName;
}
public DocumentProcessingResult ProcessDocument(
string inputPath,
string outputPath,
bool sanitize = true,
bool redactPatterns = true,
bool redactRegions = true,
bool cleanMetadata = true,
List<string> additionalTermsToRedact = null)
{
var result = new DocumentProcessingResult
{
OriginalFile = inputPath,
OutputFile = outputPath,
ProcessedAt = DateTime.Now
};
try
{
// Load the document
PdfDocument pdf = PdfDocument.FromFile(inputPath);
// Step 1: Security scan
CleanerScanResult scanResult = Cleaner.ScanPdf(pdf);
if (scanResult.IsDetected && scanResult.Risks.Count > 10)
{
throw new SecurityException("Document contains too many security risks to process");
}
// Step 2: Sanitization (if needed or requested)
if (sanitize || scanResult.IsDetected)
{
pdf = Cleaner.SanitizeWithSvg(pdf);
result.WasSanitized = true;
}
// Step 3: Pattern-based text redaction
if (redactPatterns)
{
string fullText = pdf.ExtractAllText();
HashSet<string> valuesToRedact = new HashSet<string>();
foreach (var pattern in _sensitivePatterns)
{
Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(fullText);
if (matches.Count > 0)
{
result.SensitiveDataTypesFound.Add($"{pattern.Key} ({matches.Count})");
foreach (Match match in matches)
{
valuesToRedact.Add(match.Value);
}
}
}
// Apply redactions
foreach (string value in valuesToRedact)
{
pdf.RedactTextOnAllPages(value);
result.TextRedactionsApplied++;
}
}
// Step 4: Additional specific terms
if (additionalTermsToRedact != null)
{
foreach (string term in additionalTermsToRedact)
{
pdf.RedactTextOnAllPages(term);
result.TextRedactionsApplied++;
}
}
// Step 5: Region-based redaction
if (redactRegions)
{
foreach (RectangleF region in _standardRedactionRegions)
{
pdf.RedactRegionsOnAllPages(region);
result.RegionRedactionsApplied++;
}
}
// Step 6: Metadata cleaning
if (cleanMetadata)
{
pdf.MetaData.Author = _organizationName;
pdf.MetaData.Creator = $"{_organizationName} Document Processor";
pdf.MetaData.Producer = "";
pdf.MetaData.Subject = "";
pdf.MetaData.Keywords = "";
pdf.MetaData.CreationDate = DateTime.Now;
pdf.MetaData.ModifiedDate = DateTime.Now;
result.MetadataCleaned = true;
}
// Step 7: Save the processed document
pdf.SaveAs(outputPath);
result.Success = true;
}
catch (Exception ex)
{
result.Success = false;
result.ErrorMessage = ex.Message;
}
return result;
}
}
// Usage example
class Program
{
static void Main()
{
var processor = new ComprehensiveDocumentProcessor("Acme Corporation");
// Process a single document with all protections
var result = processor.ProcessDocument(
inputPath: "customer-application.pdf",
outputPath: "customer-application-redacted.pdf",
sanitize: true,
redactPatterns: true,
redactRegions: true,
cleanMetadata: true,
additionalTermsToRedact: new List<string> { "Project Alpha", "Internal Use Only" }
);
// Batch process multiple documents
string[] inputFiles = Directory.GetFiles("incoming", "*.pdf");
foreach (string file in inputFiles)
{
string outputFile = Path.Combine("processed", Path.GetFileName(file));
processor.ProcessDocument(file, outputFile);
}
}
}
```
#### Wejscie
Formularz zgłoszeniowy klienta zawierający wiele rodzajów danych wrażliwych, w tym numery ubezpieczenia społecznego, numery kart kredytowych, adresy e-mail i bloki podpisów, wymagające kompleksowej ochrony.
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/09-complete-pipeline-before.pdf" width="100%" height="400px">
</iframe>
#### Przykładowy Wynik
<iframe loading="lazy" src="/static-assets/pdf/tutorials/pdf-redaction-csharp/09-complete-pipeline-after.pdf" width="100%" height="400px">
</iframe>
Ten wszechstronny procesor łączy wszystkie techniki omówione w tym przewodniku w jedną, konfigurowalną klasę. Wyszukuje zagrożenia, w razie potrzeby oczyszcza dane, wyszukuje i redaguje wrażliwe wzorce, stosuje redagowanie regionów, czyści metadane i generuje szczegółowe raporty. Możesz dostosować wzorce wrażliwości, obszary redagowania i opcje przetwarzania, aby dopasować je do swoich konkretnych wymagań.
---
<a id="anchor-next-steps"></a>
## Kolejne kroki
Ochrona poufnych informacji w dokumentach PDF wymaga czegoś więcej niż tylko powierzchownych środków. Prawdziwa redakcja trwałe usuwa treść ze struktury dokumentu. [Dopasowywanie wzorców](/how-to/redact-text/) automatyzuje wykrywanie i usuwanie danych, takich jak numery ubezpieczenia społecznego, dane kart kredytowych i adresy e-mail. Redakcja oparta na regionach zajmuje się podpisami, zdjęciami i innymi elementami graficznymi, których nie można uwzględnić w dopasowaniu tekstu. [Czyszczenie metadanych](/how-to/metadata/) eliminuje ukryte informacje, które mogłyby ujawnić autorów, znaczniki czasu lub wewnętrzne ścieżki plików. [Oczyszczanie](/how-to/sanitize-pdf/) usuwa osadzone skrypty i aktywną zawartość, które stanowią zagrożenie dla bezpieczeństwa.
[IronPDF](https://ironpdf.com/) zapewnia wszystkie te możliwości poprzez spójny, dobrze zaprojektowany interfejs API, który w naturalny sposób integruje się z praktykami programistycznymi w języku C# i platformie .NET. Metody przedstawione w tym przewodniku obsługują pojedyncze dokumenty lub skalują się do [przetwarzania wsadowego](/tutorials/batch-pdf-processing-csharp/) tysięcy plików. Niezależnie od tego, czy tworzysz [procesy zapewnienia zgodności](/tutorials/csharp-pdf-security-complete-tutorial/) dla danych medycznych, przygotowujesz dokumenty prawne do ujawnienia, czy po prostu dbasz o to, by raporty wewnętrzne mogły być bezpiecznie udostępniane na zewnątrz, techniki te stanowią podstawę odpowiedzialnego postępowania z dokumentami. Aby zapewnić kompleksową ochronę bezpieczeństwa, należy połączyć redagowanie z [ochroną hasłem, uprawnieniami](/how-to/pdf-permissions-passwords/) i [podpisami cyfrowymi](/how-to/signing/).
Czy jesteś gotowy do rozpoczęcia budowy? [Pobierz IronPDF](download-modal) i wyprobuj go z darmowa wersja probna. Biblioteka zawiera bezpłatną licencję deweloperską, dzięki czemu można w pełni ocenić możliwości redagowania, [ekstrakcji tekstu](/how-to/extract-text-and-images/) i czyszczenia danych przed zakupem licencji produkcyjnej. Jeśli masz pytania dotyczące wdrażania lub procesów zapewnienia zgodności, [skontaktuj się z naszym zespołem wsparcia technicznego](/troubleshooting/engineering-request-pdf/).
Redakcja PDF w C# .NET za pomocą IronPDF trwałe usuwa poufne treści z wewnętrznej struktury dokumentu, nie tylko wizualnie je zakrywając, co uniemożliwia odzyskanie oryginalnych danych poprzez kopiowanie, wyszukiwanie czy analizę kryminalistyczną. To wychodzi daleko poza czarne prostokąty nad tekstem: IronPDF oferuje redakcję tekstu z dopasowywaniem wzorców regex, redakcję opartą na regionach dla podpisów i obrazów, usuwanie metadanych, czyszczenie dokumentów w celu usunięcia osadzonych skryptów oraz skanowanie podatności, dając programistom .NET pełne narzędzia do zgodnego z HIPAA, GDPR i PCI DSS zabezpieczania dokumentów.
TL;DR: Przewodnik Quickstart
Ten poradnik obejmuje trwałe usuwanie poufnych treści z dokumentów PDF w C# .NET, w tym wzorce tekstowe, obszary obrazów, metadane i osadzone skrypty.
Kto to jest: Programiści .NET zajmujący się poufnymi dokumentami w branży medycznej, prawnej, finansowej lub rządowej.
Co zbudujesz: Redakcja tekstu z dopasowywaniem wzorców regex (SSN, karty kredytowe, e-maile), redakcja obszarów oparta na współrzędnych dla podpisów i zdjęć, czyszczenie metadanych, czyszczenie PDF w celu usunięcia osadzonych skryptów oraz skanowanie podatności oparte na YARA.
Gdzie działa: .NET 10, .NET 8 LTS, .NET Framework 4.6.2+ i .NET Standard 2.0. Wszystkie operacje działają lokalnie, bez zewnętrznych zależności.
Kiedy używać tego podejścia: Gdy musisz udostępnić dokumenty w celu odkrywania prawnego, na potrzeby wniosków FOIA lub dystrybucji zewnętrznej, zapewniając, że usunięta treść jest naprawdę usunięta.
Dlaczego to ma znaczenie technicznie: Nakładki wizualne pozostawiają oryginalny tekst odzyskiwalnym w strumieniach treści PDF. Redakcja IronPDF usuwa dane znakowe z samej struktury dokumentu, co uniemożliwia ich odzyskanie.
Redagowanie poufnego tekstu z PDF za pomocą kilku linii kodu:
1Install IronPDF with NuGet Package Manager
PM > Install-Package IronPdf
Install-Package IronPdf
2Skopiuj i uruchom ten fragment kodu.
using IronPdf;PdfDocument pdf = PdfDocument.FromFile("confidential-report.pdf");pdf.RedactTextOnAllPages("CONFIDENTIAL");pdf.SaveAs("redacted-report.pdf");
using IronPdf;
PdfDocument pdf = PdfDocument.FromFile("confidential-report.pdf");
pdf.RedactTextOnAllPages("CONFIDENTIAL");
pdf.SaveAs("redacted-report.pdf");
C#
3Wdrożenie do testowania w środowisku produkcyjnym
Jaka jest różnica między prawdziwą redakcją a wizualnym nakładką?
Zrozumienie różnicy między prawdziwą redakcją a wizualną nakładką jest kluczowe dla każdego zajmującego się poufnymi dokumentami. Wiele narzędzi i metod manualnych tworzy wrażenie redakcji bez faktycznego usunięcia danych źródłowych. To fałszywe poczucie bezpieczeństwa spowodowało liczne głośne naruszenia danych i niepowodzenia w zakresie zgodności.
Podejścia wizualne typowo rysują nieprzejrzyste kształty nad wrażliwą treścią. Tekst pozostaje w pełni nienaruszony w strukturze PDF. Ktoś oglądający dokument widzi czarny prostokąt, ale oryginalne znaki wciąż istnieją w strumieniach treści pliku. Wybór całego tekstu na stronie, użycie narzędzi dostępności czy badanie surowych danych PDF ujawni wszystko, co miało być ukryte. Sprawy sądowe zostały skompromitowane, gdy zredagowane zgłoszenia zostały łatwo odredagowane przez stronę przeciwna. Agencje rządowe przypadkowo ujawniły informacje oznaczone jako tajne, które wydawały się ukryte, ale były w pełni odzyskiwalne.
Prawdziwa redakcja działa inaczej. Gdy używasz metod redakcji IronPDF, biblioteka lokalizuje określony tekst w wewnętrznej strukturze PDF i całkowicie go usuwa. Dane znakowe są usuwane z strumieni treści. Reprezentacja wizualna jest zastępowana przez znak redakcji, zazwyczaj czarny prostokąt, ale oryginalna treść już nigdzie nie istnieje w pliku. Żadne zaznaczenia, kopiowanie ani analiza kryminalistyczna nie mogą odzyskać tego, co zostało trwałe usunięte.
IronPDF implementuje prawdziwą redakcję poprzez modyfikację PDF na poziomie strukturalnym. Metoda RedactTextOnAllPages i jej odmiany przeszukują treść strony, identyfikują dopasowany tekst, usuwają go z modelu obiektu dokumentu i opcjonalnie rysują wizualny wskaźnik tam, gdzie ta treść się znajdowała. To podejście jest zgodne z wytycznymi organizacji takich jak NIST dotyczących bezpiecznej redakcji dokumentów.
Praktyczne konsekwencje są znaczące. Jeśli musisz udostępniać dokumenty zewnętrznie, zgłaszać pliki do odkrywania prawnego, publikować zasoby w ramach wniosków o dostęp do informacji lub dystrybuować raporty, chroniąc dane umożliwiające identyfikację osobistą, tylko prawdziwa redakcja zapewnia odpowiednią ochronę. Wizualne nakładki mogą wystarczyć na wewnętrzne wersje robocze, gdy po prostu chcesz odwrócić uwagę od pewnych sekcji, ale nigdy nie powinno się im ufać w kontekście rzeczywistej ochrony danych. Dla dodatkowych środków bezpieczeństwa dokumentów zobacz nasze przewodniki dotyczące szyfrowania PDF i podpisów cyfrowych.
How do I Redact PDF Text in C# Across an Entire Document?
Najczęstszy scenariusz redakcji obejmuje usunięcie wszystkich wystąpień konkretnego tekstu w całym dokumencie. Być może musisz usunąć czyjeś imię z raportu, numery kont z oświadczeń finansowych lub wewnętrzne kody referencyjne przed dystrybucją zewnętrzną. IronPDF ułatwia to dzięki metodzie RedactTextOnAllPages.
Wejscie
Dokument rejestrów pracowniczych zawierający informacje osobiste, w tym imiona, numery ubezpieczenia społecznego i identyfikatory pracowników.
using IronPdf;// Load the source documentPdfDocument pdf = PdfDocument.FromFile("employee-records.pdf");// Redact an employee name from the entire documentpdf.RedactTextOnAllPages("John Smith");// Redact a Social Security Numberpdf.RedactTextOnAllPages("123-45-6789");// Redact an internal employee IDpdf.RedactTextOnAllPages("EMP-2024-0042");// Save the cleaned documentpdf.SaveAs("employee-records-redacted.pdf");
using IronPdf;
// Load the source document
PdfDocument pdf = PdfDocument.FromFile("employee-records.pdf");
// Redact an employee name from the entire document
pdf.RedactTextOnAllPages("John Smith");
// Redact a Social Security Number
pdf.RedactTextOnAllPages("123-45-6789");
// Redact an internal employee ID
pdf.RedactTextOnAllPages("EMP-2024-0042");
// Save the cleaned document
pdf.SaveAs("employee-records-redacted.pdf");
ImportsIronPdf' Load the source documentDim pdf AsPdfDocument = PdfDocument.FromFile("employee-records.pdf")' Redact an employee name from the entire documentpdf.RedactTextOnAllPages("John Smith")' Redact a Social Security Numberpdf.RedactTextOnAllPages("123-45-6789")' Redact an internal employee IDpdf.RedactTextOnAllPages("EMP-2024-0042")' Save the cleaned documentpdf.SaveAs("employee-records-redacted.pdf")
Imports IronPdf
' Load the source document
Dim pdf As PdfDocument = PdfDocument.FromFile("employee-records.pdf")
' Redact an employee name from the entire document
pdf.RedactTextOnAllPages("John Smith")
' Redact a Social Security Number
pdf.RedactTextOnAllPages("123-45-6789")
' Redact an internal employee ID
pdf.RedactTextOnAllPages("EMP-2024-0042")
' Save the cleaned document
pdf.SaveAs("employee-records-redacted.pdf")
Ten kod ładuje PDF zawierający informacje o pracowniku i usuwa trzy fragmenty poufnych danych, wywołując RedactTextOnAllPages dla każdej wartości. Każde wywołanie przeszukuje każdą stronę dokumentu i trwałe usuwa wszystkie pasujące przypadki imienia pracownika, numeru ubezpieczenia społecznego i wewnętrznego identyfikatora.
Przykładowy Wynik
Domyślne zachowanie rysuje czarne prostokąty, gdzie pojawiał się zredagowany tekst, i zastępuje rzeczywiste znaki gwiazdkami w strukturze dokumentu. Zapewnia to zarówno wizualne potwierdzenie, że redakcja miała miejsce, jak i gwarantuje, że oryginalna treść została całkowicie usunięta.
W przypadku pracy z dłuższymi dokumentami lub wieloma celami redakcji można efektywnie łączyć te wywołania:
using IronPdf;using System.Collections.Generic;// Load the document oncePdfDocument pdf = PdfDocument.FromFile("quarterly-report.pdf");// Define all terms that need redactionList<string> sensitiveTerms = new List<string>{ "Project Titan", "Sarah Johnson", "Budget: $4.2M", "Q3-INTERNAL-2024", "sarah.johnson@company.com"};// Redact each termforeach (string term in sensitiveTerms){ pdf.RedactTextOnAllPages(term);}// Save the resultpdf.SaveAs("quarterly-report-public.pdf");
using IronPdf;
using System.Collections.Generic;
// Load the document once
PdfDocument pdf = PdfDocument.FromFile("quarterly-report.pdf");
// Define all terms that need redaction
List<string> sensitiveTerms = new List<string>
{
"Project Titan",
"Sarah Johnson",
"Budget: $4.2M",
"Q3-INTERNAL-2024",
"sarah.johnson@company.com"
};
// Redact each term
foreach (string term in sensitiveTerms)
{
pdf.RedactTextOnAllPages(term);
}
// Save the result
pdf.SaveAs("quarterly-report-public.pdf");
ImportsIronPdfImportsSystem.Collections.Generic' Load the document onceDim pdf AsPdfDocument = PdfDocument.FromFile("quarterly-report.pdf")' Define all terms that need redactionDim sensitiveTerms As New List(OfString) From { "Project Titan", "Sarah Johnson", "Budget: $4.2M", "Q3-INTERNAL-2024", "sarah.johnson@company.com"}' Redact each termFor Each term AsStringIn sensitiveTerms pdf.RedactTextOnAllPages(term)Next' Save the resultpdf.SaveAs("quarterly-report-public.pdf")
Imports IronPdf
Imports System.Collections.Generic
' Load the document once
Dim pdf As PdfDocument = PdfDocument.FromFile("quarterly-report.pdf")
' Define all terms that need redaction
Dim sensitiveTerms As New List(Of String) From {
"Project Titan",
"Sarah Johnson",
"Budget: $4.2M",
"Q3-INTERNAL-2024",
"sarah.johnson@company.com"
}
' Redact each term
For Each term As String In sensitiveTerms
pdf.RedactTextOnAllPages(term)
Next
' Save the result
pdf.SaveAs("quarterly-report-public.pdf")
Ten wzorzec sprawdza się dobrze, gdy dysponujesz znaną listą wrażliwych wartości, które należy usunąć. Dokument jest ładowany jednokrotnie, wszystkie zmiany są wprowadzane w pamięci, a ostateczny wynik jest zapisywany. Każdy termin jest przetwarzany niezależnie, więc częściowe dopasowania lub różnice w formatowaniu między terminami nie mają wpływu na inne tłumaczenia.
Jak mogę zredagować tekst tylko na określonych stronach?
Czasami potrzebna jest bardziej precyzyjna kontrola nad miejscami, w których występują redakcje. Dokument może zawierać stronę tytułową z informacjami, które powinny pozostać niezmienione, lub może być wiadomo, że dane poufne pojawiają się tylko w niektórych sekcjach. IronPDF oferuje RedactTextOnPage dla pojedynczej strony i RedactTextOnPages dla wycelowania w wiele określonych stron.
Wejscie
Wielostronicowy pakiet umów z nazwami klientów na stronie podpisowej oraz warunkami finansowymi umieszczonymi na określonych stronach w całym dokumencie.
using IronPdf;// Load the documentPdfDocument pdf = PdfDocument.FromFile("contract-bundle.pdf");// Redact text only on page 1 (index 0)pdf.RedactTextOnPage(0, "Client Name: Acme Corporation");// Redact text on pages 3, 5, and 7 (indices 2, 4, 6)int[] financialPages = { 2, 4, 6 };pdf.RedactTextOnPages(financialPages, "Payment Terms: Net 30");// Other pages remain untouched except for the specific redactions appliedpdf.SaveAs("contract-bundle-redacted.pdf");
using IronPdf;
// Load the document
PdfDocument pdf = PdfDocument.FromFile("contract-bundle.pdf");
// Redact text only on page 1 (index 0)
pdf.RedactTextOnPage(0, "Client Name: Acme Corporation");
// Redact text on pages 3, 5, and 7 (indices 2, 4, 6)
int[] financialPages = { 2, 4, 6 };
pdf.RedactTextOnPages(financialPages, "Payment Terms: Net 30");
// Other pages remain untouched except for the specific redactions applied
pdf.SaveAs("contract-bundle-redacted.pdf");
ImportsIronPdf' Load the documentDim pdf AsPdfDocument = PdfDocument.FromFile("contract-bundle.pdf")' Redact text only on page 1 (index 0)pdf.RedactTextOnPage(0, "Client Name: Acme Corporation")' Redact text on pages 3, 5, and 7 (indices 2, 4, 6)Dim financialPages AsInteger() = {2, 4, 6}pdf.RedactTextOnPages(financialPages, "Payment Terms: Net 30")' Other pages remain untouched except for the specific redactions appliedpdf.SaveAs("contract-bundle-redacted.pdf")
Imports IronPdf
' Load the document
Dim pdf As PdfDocument = PdfDocument.FromFile("contract-bundle.pdf")
' Redact text only on page 1 (index 0)
pdf.RedactTextOnPage(0, "Client Name: Acme Corporation")
' Redact text on pages 3, 5, and 7 (indices 2, 4, 6)
Dim financialPages As Integer() = {2, 4, 6}
pdf.RedactTextOnPages(financialPages, "Payment Terms: Net 30")
' Other pages remain untouched except for the specific redactions applied
pdf.SaveAs("contract-bundle-redacted.pdf")
Ten kod demonstruje selektywną redakcję, używając RedactTextOnPage dla pojedynczej strony i RedactTextOnPages dla wielu określonych stron. Nazwa klienta została usunięta tylko ze strony 1 (indeks 0), natomiast warunki płatności zostały usunięte ze stron 3, 5 i 7 (indeksy 2, 4, 6), pozostawiając pozostałe strony bez zmian.
Przykładowy Wynik
Indeksy stron w IronPDF są zerowe, co oznacza, że pierwsza strona ma indeks 0, druga 1 i tak dalej. Jest to zgodne ze standardowymi konwencjami programistycznymi i odpowiada sposobowi, w jaki większość programistów postrzega dostęp do tablic.
Skierowanie na konkretne strony poprawia wydajność podczas przetwarzania dużych dokumentów. Zamiast przeszukiwać setki stron w poszukiwaniu tekstu, który pojawia się tylko w kilku miejscach, możesz wskazać silnikowi redakcyjnemu dokładnie, gdzie ma szukać. Ma to znaczenie w scenariuszach przetwarzania wsadowego, w których może być przetwarzanych tysiące dokumentów. Aby uzyskać maksymalną przepustowość, warto rozważyć zastosowanie technik asynchronicznych i wielowątkowych.
using IronPdf;// Process a large document efficientlyPdfDocument pdf = PdfDocument.FromFile("annual-report-500-pages.pdf");// We know from document structure that:// - Executive summary with names is on pages 1-3// - Financial data is on pages 45-60// - Appendix with employee info is on pages 480-495// Redact executive names from summary sectionfor (int i = 0; i <= 2; i++){ pdf.RedactTextOnPage(i, "CEO: Robert Williams"); pdf.RedactTextOnPage(i, "CFO: Maria Garcia");}// Redact specific financial figures from the financial sectionint[] financialSection = { 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 };pdf.RedactTextOnPages(financialSection, "Net Revenue: $847M");// Redact employee identifiers from appendixfor (int i = 479; i <= 494; i++){ pdf.RedactTextOnPage(i, "Employee ID:");}pdf.SaveAs("annual-report-public-release.pdf");
using IronPdf;
// Process a large document efficiently
PdfDocument pdf = PdfDocument.FromFile("annual-report-500-pages.pdf");
// We know from document structure that:
// - Executive summary with names is on pages 1-3
// - Financial data is on pages 45-60
// - Appendix with employee info is on pages 480-495
// Redact executive names from summary section
for (int i = 0; i <= 2; i++)
{
pdf.RedactTextOnPage(i, "CEO: Robert Williams");
pdf.RedactTextOnPage(i, "CFO: Maria Garcia");
}
// Redact specific financial figures from the financial section
int[] financialSection = { 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 };
pdf.RedactTextOnPages(financialSection, "Net Revenue: $847M");
// Redact employee identifiers from appendix
for (int i = 479; i <= 494; i++)
{
pdf.RedactTextOnPage(i, "Employee ID:");
}
pdf.SaveAs("annual-report-public-release.pdf");
ImportsIronPdf' Process a large document efficientlyDim pdf AsPdfDocument = PdfDocument.FromFile("annual-report-500-pages.pdf")' We know from document structure that:' - Executive summary with names is on pages 1-3' - Financial data is on pages 45-60' - Appendix with employee info is on pages 480-495' Redact executive names from summary sectionFor i AsInteger = 0 To 2 pdf.RedactTextOnPage(i, "CEO: Robert Williams") pdf.RedactTextOnPage(i, "CFO: Maria Garcia")Next' Redact specific financial figures from the financial sectionDim financialSection AsInteger() = {44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}pdf.RedactTextOnPages(financialSection, "Net Revenue: $847M")' Redact employee identifiers from appendixFor i AsInteger = 479 To 494 pdf.RedactTextOnPage(i, "Employee ID:")Nextpdf.SaveAs("annual-report-public-release.pdf")
Imports IronPdf
' Process a large document efficiently
Dim pdf As PdfDocument = PdfDocument.FromFile("annual-report-500-pages.pdf")
' We know from document structure that:
' - Executive summary with names is on pages 1-3
' - Financial data is on pages 45-60
' - Appendix with employee info is on pages 480-495
' Redact executive names from summary section
For i As Integer = 0 To 2
pdf.RedactTextOnPage(i, "CEO: Robert Williams")
pdf.RedactTextOnPage(i, "CFO: Maria Garcia")
Next
' Redact specific financial figures from the financial section
Dim financialSection As Integer() = {44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}
pdf.RedactTextOnPages(financialSection, "Net Revenue: $847M")
' Redact employee identifiers from appendix
For i As Integer = 479 To 494
pdf.RedactTextOnPage(i, "Employee ID:")
Next
pdf.SaveAs("annual-report-public-release.pdf")
To ukierunkowane podejście przetwarza tylko odpowiednie sekcje 500-stronicowego dokumentu, znacznie skracając czas wykonania w porównaniu do skanowania każdej strony dla każdego terminu redakcyjnego.
Jak dostosować wygląd zredagowanej treści?
IronPDF oferuje kilka parametrów pozwalających kontrolować sposób wyświetlania redakcji w ostatecznej wersji dokumentu. Można dostosować wrażliwość na wielkość liter, dopasowanie całych słów, wyświetlanie prostokątów oraz tekst zastępczy wyświetlany w miejscu usuniętej treści.
Wejscie
Dokument prawny zawierający różne wrażliwe terminy, w tym oznaczenia klasyfikacyjne, hasła i wewnętrzne kody referencyjne, które wymagają różnych metod redagowania.
using IronPdf;// Load the documentPdfDocument pdf = PdfDocument.FromFile("legal-brief.pdf");// Case-sensitive redaction: only matches exact case// "CLASSIFIED" will be redacted but "classified" or "Classified" will notpdf.RedactTextOnAllPages( "CLASSIFIED",CaseSensitive: true,OnlyMatchWholeWords: true,DrawRectangles: true,ReplacementText: "[REDACTED]");// Case-insensitive redaction: matches regardless of case// Will redact "Secret", "SECRET", "secret", etc.pdf.RedactTextOnAllPages( "secret",CaseSensitive: false,OnlyMatchWholeWords: true,DrawRectangles: true,ReplacementText: "*****");// Whole word disabled: matches partial strings too// Will redact "password", "passwords", "mypassword123", etc.pdf.RedactTextOnAllPages( "password",CaseSensitive: false,OnlyMatchWholeWords: false,DrawRectangles: true,ReplacementText: "XXXXX");// No visual rectangle: text is removed but no black box appears// Useful when you want seamless removal without obvious redaction markspdf.RedactTextOnAllPages( "internal-reference-code",CaseSensitive: true,OnlyMatchWholeWords: true,DrawRectangles: false,ReplacementText: "");pdf.SaveAs("legal-brief-redacted.pdf");
using IronPdf;
// Load the document
PdfDocument pdf = PdfDocument.FromFile("legal-brief.pdf");
// Case-sensitive redaction: only matches exact case
// "CLASSIFIED" will be redacted but "classified" or "Classified" will not
pdf.RedactTextOnAllPages(
"CLASSIFIED",
CaseSensitive: true,
OnlyMatchWholeWords: true,
DrawRectangles: true,
ReplacementText: "[REDACTED]"
);
// Case-insensitive redaction: matches regardless of case
// Will redact "Secret", "SECRET", "secret", etc.
pdf.RedactTextOnAllPages(
"secret",
CaseSensitive: false,
OnlyMatchWholeWords: true,
DrawRectangles: true,
ReplacementText: "*****"
);
// Whole word disabled: matches partial strings too
// Will redact "password", "passwords", "mypassword123", etc.
pdf.RedactTextOnAllPages(
"password",
CaseSensitive: false,
OnlyMatchWholeWords: false,
DrawRectangles: true,
ReplacementText: "XXXXX"
);
// No visual rectangle: text is removed but no black box appears
// Useful when you want seamless removal without obvious redaction marks
pdf.RedactTextOnAllPages(
"internal-reference-code",
CaseSensitive: true,
OnlyMatchWholeWords: true,
DrawRectangles: false,
ReplacementText: ""
);
pdf.SaveAs("legal-brief-redacted.pdf");
ImportsIronPdf' Load the documentDim pdf AsPdfDocument = PdfDocument.FromFile("legal-brief.pdf")' Case-sensitive redaction: only matches exact case' "CLASSIFIED" will be redacted but "classified" or "Classified" will notpdf.RedactTextOnAllPages( "CLASSIFIED",CaseSensitive:=True,OnlyMatchWholeWords:=True,DrawRectangles:=True,ReplacementText:="[REDACTED]")' Case-insensitive redaction: matches regardless of case' Will redact "Secret", "SECRET", "secret", etc.pdf.RedactTextOnAllPages( "secret",CaseSensitive:=False,OnlyMatchWholeWords:=True,DrawRectangles:=True,ReplacementText:="*****")' Whole word disabled: matches partial strings too' Will redact "password", "passwords", "mypassword123", etc.pdf.RedactTextOnAllPages( "password",CaseSensitive:=False,OnlyMatchWholeWords:=False,DrawRectangles:=True,ReplacementText:="XXXXX")' No visual rectangle: text is removed but no black box appears' Useful when you want seamless removal without obvious redaction markspdf.RedactTextOnAllPages( "internal-reference-code",CaseSensitive:=True,OnlyMatchWholeWords:=True,DrawRectangles:=False,ReplacementText:="")pdf.SaveAs("legal-brief-redacted.pdf")
Imports IronPdf
' Load the document
Dim pdf As PdfDocument = PdfDocument.FromFile("legal-brief.pdf")
' Case-sensitive redaction: only matches exact case
' "CLASSIFIED" will be redacted but "classified" or "Classified" will not
pdf.RedactTextOnAllPages(
"CLASSIFIED",
CaseSensitive:=True,
OnlyMatchWholeWords:=True,
DrawRectangles:=True,
ReplacementText:="[REDACTED]"
)
' Case-insensitive redaction: matches regardless of case
' Will redact "Secret", "SECRET", "secret", etc.
pdf.RedactTextOnAllPages(
"secret",
CaseSensitive:=False,
OnlyMatchWholeWords:=True,
DrawRectangles:=True,
ReplacementText:="*****"
)
' Whole word disabled: matches partial strings too
' Will redact "password", "passwords", "mypassword123", etc.
pdf.RedactTextOnAllPages(
"password",
CaseSensitive:=False,
OnlyMatchWholeWords:=False,
DrawRectangles:=True,
ReplacementText:="XXXXX"
)
' No visual rectangle: text is removed but no black box appears
' Useful when you want seamless removal without obvious redaction marks
pdf.RedactTextOnAllPages(
"internal-reference-code",
CaseSensitive:=True,
OnlyMatchWholeWords:=True,
DrawRectangles:=False,
ReplacementText:=""
)
pdf.SaveAs("legal-brief-redacted.pdf")
Ten kod pokazuje cztery różne konfiguracje redakcji, używając opcjonalnych parametrów RedactTextOnAllPages. Pokazuje dopasowanie dokładne z uwzględnieniem wielkości liter z zastąpieniem "[REDACTED]", dopasowanie bez uwzględnienia wielkości liter z gwiazdkami, dopasowanie częściowe słów w celu wychwycenia odmian takich jak "hasła" oraz niewidoczne usuwanie bez wizualnych prostokątów w celu płynnej eliminacji treści.
Przykładowy Wynik
Parametry służą różnym celom w zależności od wymagań:
CaseSensitive określa, czy dopasowanie uwzględnia wielkość liter. Dokumenty prawne często używają specyficznych kapitalizacji, które mają konkretne znaczenie, dlatego porównanie uwzględniające wielkość liter zapewnia, że usuwasz tylko dokładne dopasowania. Przetwarzanie ogólnego tekstu, gdzie wielkość liter może się różnić, może wymagać porównania bez względu na wielkość liter, aby uchwycić wszystkie przypadki.
OnlyMatchWholeWords kontroluje, czy wyszukiwanie pasuje do całych słów czy częściowych ciągów. Podczas redagowania nazw zazwyczaj pożądane jest dopasowanie całych słów, tak aby "Smith" nie spowodowało przypadkowego usunięcia części słowa "Blacksmith" lub "Smithfield". Podczas redagowania wzorców, takich jak prefiksy numerów kont, może być konieczne stosowanie dopasowania częściowego w celu wychwycenia różnych wariantów.
DrawRectangles określa, czy czarne prostokąty pojawiają się tam, gdzie usunięto treść. Większość kontekstów regulacyjnych i prawnych wymaga widocznych znaków redakcyjnych jako dowodu, że treść została celowo usunięta, a nie przypadkowo pominięta. Wewnętrzne procesy robocze mogą preferować niewidoczne usunięcie w celu uzyskania bardziej przejrzystego wyniku.
ReplacementText definiuje, jakie znaki pojawiają się zamiast zredagowanej treści. Typowe rozwiązania to gwiazdki, oznaczenia "REDACTED" lub puste ciągi znaków. Tekst zastępczy pojawia się w strukturze dokumentu, jeśli ktoś spróbuje zaznaczyć lub skopiować fragment z zacenzurowanego obszaru.
Jak mogę używać wyrażeń regularnych do wyszukiwania i redagowania wrażliwych wzorców?
Redagowanie znanych ciągów tekstowych sprawdza się, gdy masz konkretne wartości do usunięcia, ale wiele typów danych poufnych ma raczej przewidywalne wzorce niż stałe wartości. Numery ubezpieczenia społecznego, numery kart kredytowych, adresy e-mail, numery telefonów i daty mają rozpoznawalne formaty, które można dopasować za pomocą wyrażeń regularnych. Budowa systemu redakcji opartego na wzorach umożliwia usunięcie prywatnych informacji z treści PDF bez znajomości każdej konkretnej wartości z góry.
Możliwości IronPDF wzakresie ekstrakcji tekstu w połączeniu z metodami redagowania umożliwiają tworzenie wydajnych procesów dopasowywania wzorców. Wyodrębniasz tekst, identyfikujesz dopasowania za pomocą wyrażeń regularnych .NET, a następnie redagujesz każdą wykrytą wartość.
using IronPdf;using System.Text.RegularExpressions;using System.Collections.Generic;public class PatternRedactor{ // Common patterns for sensitive data private static readonly Dictionary<string, string> SensitivePatterns = new Dictionary<string, string> { // US Social Security Number: 123-45-6789 { "SSN", @"\b\d{3}-\d{2}-\d{4}\b" }, // Credit Card Numbers: various formats with 13-19 digits { "CreditCard", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" }, // Email Addresses { "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" }, // US Phone Numbers: (123) 456-7890 or 123-456-7890 { "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" }, // Dates: MM/DD/YYYY or MM-DD-YYYY { "Date", @"\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" }, // IP Addresses { "IPAddress", @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b" } }; public voidRedactPatterns(string inputPath, string outputPath, params string[] patternNames) { // Load the PDF PdfDocument pdf = PdfDocument.FromFile(inputPath); // Extract all text from the document string fullText = pdf.ExtractAllText(); // Track unique matches to avoid duplicate redaction attempts HashSet<string> matchesToRedact = new HashSet<string>(); // Find all matches for requested patterns foreach (string patternName in patternNames) { if (SensitivePatterns.TryGetValue(patternName, out string pattern)) { Regex regex = new Regex(pattern, RegexOptions.IgnoreCase); MatchCollection matches = regex.Matches(fullText); foreach (Match match in matches) { matchesToRedact.Add(match.Value); } } } // Redact each unique match foreach (string sensitiveValue in matchesToRedact) { pdf.RedactTextOnAllPages(sensitiveValue); } // Save the redacted document pdf.SaveAs(outputPath); }}// Usage exampleclass Program{ static voidMain() { PatternRedactor redactor = new PatternRedactor(); // Redact SSNs and credit cards from a financial document redactor.RedactPatterns( "customer-data.pdf", "customer-data-safe.pdf", "SSN", "CreditCard", "Email" ); }}
using IronPdf;
using System.Text.RegularExpressions;
using System.Collections.Generic;
public class PatternRedactor
{
// Common patterns for sensitive data
private static readonly Dictionary<string, string> SensitivePatterns = new Dictionary<string, string>
{
// US Social Security Number: 123-45-6789
{ "SSN", @"\b\d{3}-\d{2}-\d{4}\b" },
// Credit Card Numbers: various formats with 13-19 digits
{ "CreditCard", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
// Email Addresses
{ "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
// US Phone Numbers: (123) 456-7890 or 123-456-7890
{ "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" },
// Dates: MM/DD/YYYY or MM-DD-YYYY
{ "Date", @"\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" },
// IP Addresses
{ "IPAddress", @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b" }
};
public void RedactPatterns(string inputPath, string outputPath, params string[] patternNames)
{
// Load the PDF
PdfDocument pdf = PdfDocument.FromFile(inputPath);
// Extract all text from the document
string fullText = pdf.ExtractAllText();
// Track unique matches to avoid duplicate redaction attempts
HashSet<string> matchesToRedact = new HashSet<string>();
// Find all matches for requested patterns
foreach (string patternName in patternNames)
{
if (SensitivePatterns.TryGetValue(patternName, out string pattern))
{
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(fullText);
foreach (Match match in matches)
{
matchesToRedact.Add(match.Value);
}
}
}
// Redact each unique match
foreach (string sensitiveValue in matchesToRedact)
{
pdf.RedactTextOnAllPages(sensitiveValue);
}
// Save the redacted document
pdf.SaveAs(outputPath);
}
}
// Usage example
class Program
{
static void Main()
{
PatternRedactor redactor = new PatternRedactor();
// Redact SSNs and credit cards from a financial document
redactor.RedactPatterns(
"customer-data.pdf",
"customer-data-safe.pdf",
"SSN", "CreditCard", "Email"
);
}
}
ImportsIronPdfImportsSystem.Text.RegularExpressionsImportsSystem.Collections.GenericPublic Class PatternRedactor ' Common patterns for sensitive data PrivateSharedReadOnlySensitivePatternsAs New Dictionary(OfString, String) From { ' US Social Security Number: 123-45-6789 {"SSN", "\b\d{3}-\d{2}-\d{4}\b"}, ' Credit Card Numbers: various formats with 13-19 digits {"CreditCard", "\b(?:\d{4}[-\s]?){3}\d{1,4}\b"}, ' Email Addresses {"Email", "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"}, ' US Phone Numbers: (123) 456-7890 or 123-456-7890 {"Phone", "\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b"}, ' Dates: MM/DD/YYYY or MM-DD-YYYY {"Date", "\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b"}, ' IP Addresses {"IPAddress", "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"} } Public Sub RedactPatterns(inputPath AsString, outputPath AsString, ParamArray patternNames AsString()) ' Load the PDF Dim pdf AsPdfDocument = PdfDocument.FromFile(inputPath) ' Extract all text from the document Dim fullText AsString = pdf.ExtractAllText() ' Track unique matches to avoid duplicate redaction attempts Dim matchesToRedact As New HashSet(OfString)() ' Find all matches for requested patterns For Each patternName AsStringIn patternNames Dim pattern AsString = Nothing IfSensitivePatterns.TryGetValue(patternName, pattern) Then Dim regex As New Regex(pattern, RegexOptions.IgnoreCase) Dim matches AsMatchCollection = regex.Matches(fullText) For Each match AsMatchIn matches matchesToRedact.Add(match.Value) Next End If Next ' Redact each unique match For Each sensitiveValue AsStringIn matchesToRedact pdf.RedactTextOnAllPages(sensitiveValue) Next ' Save the redacted document pdf.SaveAs(outputPath) End SubEnd Class' Usage exampleClass ProgramShared Sub Main() Dim redactor As New PatternRedactor() ' Redact SSNs and credit cards from a financial document redactor.RedactPatterns( "customer-data.pdf", "customer-data-safe.pdf", "SSN", "CreditCard", "Email" ) End SubEnd Class
Imports IronPdf
Imports System.Text.RegularExpressions
Imports System.Collections.Generic
Public Class PatternRedactor
' Common patterns for sensitive data
Private Shared ReadOnly SensitivePatterns As New Dictionary(Of String, String) From {
' US Social Security Number: 123-45-6789
{"SSN", "\b\d{3}-\d{2}-\d{4}\b"},
' Credit Card Numbers: various formats with 13-19 digits
{"CreditCard", "\b(?:\d{4}[-\s]?){3}\d{1,4}\b"},
' Email Addresses
{"Email", "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"},
' US Phone Numbers: (123) 456-7890 or 123-456-7890
{"Phone", "\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b"},
' Dates: MM/DD/YYYY or MM-DD-YYYY
{"Date", "\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b"},
' IP Addresses
{"IPAddress", "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"}
}
Public Sub RedactPatterns(inputPath As String, outputPath As String, ParamArray patternNames As String())
' Load the PDF
Dim pdf As PdfDocument = PdfDocument.FromFile(inputPath)
' Extract all text from the document
Dim fullText As String = pdf.ExtractAllText()
' Track unique matches to avoid duplicate redaction attempts
Dim matchesToRedact As New HashSet(Of String)()
' Find all matches for requested patterns
For Each patternName As String In patternNames
Dim pattern As String = Nothing
If SensitivePatterns.TryGetValue(patternName, pattern) Then
Dim regex As New Regex(pattern, RegexOptions.IgnoreCase)
Dim matches As MatchCollection = regex.Matches(fullText)
For Each match As Match In matches
matchesToRedact.Add(match.Value)
Next
End If
Next
' Redact each unique match
For Each sensitiveValue As String In matchesToRedact
pdf.RedactTextOnAllPages(sensitiveValue)
Next
' Save the redacted document
pdf.SaveAs(outputPath)
End Sub
End Class
' Usage example
Class Program
Shared Sub Main()
Dim redactor As New PatternRedactor()
' Redact SSNs and credit cards from a financial document
redactor.RedactPatterns(
"customer-data.pdf",
"customer-data-safe.pdf",
"SSN", "CreditCard", "Email"
)
End Sub
End Class
To podejście oparte na wzorach dobrze się skaluje, ponieważ definiujesz wzory raz i stosujesz je do dowolnego dokumentu. Dodanie nowych typów danych wymaga jedynie dodania nowych wzorców wyrażeń regularnych do słownika.
Jak zbudować skaner danych wrażliwych, który można ponownie wykorzystać?
W środowiskach produkcyjnych często trzeba skanować dokumenty i zgłaszać, jakie informacje poufne się w nich znajdują, zanim zdecyduje się na ich redagowanie. Pomaga to w audycie zgodności i umożliwia weryfikację decyzji dotyczących redakcji przez człowieka. Poniższa klasa oferuje funkcje skanowania oraz redagowania.
using IronPdf;using System.Collections.Generic;using System.Text.RegularExpressions;using System.Linq;public class SensitiveDataMatch{ public stringPatternType { get; set; } public stringValue { get; set; } public intPageNumber { get; set; }}public class ScanResult{ public stringFilePath { get; set; } public List<SensitiveDataMatch> Matches { get; set; } = new List<SensitiveDataMatch>(); public boolContainsSensitiveData => Matches.Count > 0; public Dictionary<string, int> GetSummary() { returnMatches.GroupBy(m => m.PatternType) .ToDictionary(g => g.Key, g => g.Count()); }}public class DocumentScanner{ private readonly Dictionary<string, string> _patterns; publicDocumentScanner() { _patterns = new Dictionary<string, string> { { "Social Security Number", @"\b\d{3}-\d{2}-\d{4}\b" }, { "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" }, { "Email Address", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" }, { "Phone Number", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" }, { "Date of Birth Pattern", @"\b(?:DOB|Date of Birth|Birth Date)[:\s]+\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" } }; } public ScanResultScanDocument(string filePath) { ScanResult result = new ScanResult { FilePath = filePath }; PdfDocument pdf = PdfDocument.FromFile(filePath); // Scan each page individually to track location for (int pageIndex = 0; pageIndex < pdf.PageCount; pageIndex++) { string pageText = pdf.ExtractTextFromPage(pageIndex); foreach (var pattern in _patterns) { Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase); MatchCollection matches = regex.Matches(pageText); foreach (Match match in matches) { result.Matches.Add(new SensitiveDataMatch {PatternType = pattern.Key,Value = MaskValue(match.Value, pattern.Key),PageNumber = pageIndex + 1 }); } } } return result; } // Partially mask values for safe storage private stringMaskValue(string value, string patternType) { if (patternType == "Social Security Number" && value.Length >= 4) { return "XXX-XX-" + value.Substring(value.Length - 4); } if (patternType == "Credit Card" && value.Length >= 4) { return "****-****-****-" + value.Substring(value.Length - 4); } if (patternType == "Email Address") { int atIndex = value.IndexOf('@'); if (atIndex > 2) { return value.Substring(0, 2) + "***" + value.Substring(atIndex); } } return value.Length > 4 ? value.Substring(0, 2) + "***" : "****"; } public voidScanAndRedact(string inputPath, string outputPath) { // First scan to identify sensitive data ScanResult scanResult = ScanDocument(inputPath); if (!scanResult.ContainsSensitiveData) { return; } // Load document for redaction PdfDocument pdf = PdfDocument.FromFile(inputPath); // Extract unique actual values (not masked) for redaction string fullText = pdf.ExtractAllText(); HashSet<string> valuesToRedact = new HashSet<string>(); foreach (var pattern in _patterns) { Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase); foreach (Match match in regex.Matches(fullText)) { valuesToRedact.Add(match.Value); } } // Apply redactions foreach (string value in valuesToRedact) { pdf.RedactTextOnAllPages(value); } pdf.SaveAs(outputPath); }}// Usageclass Program{ static voidMain() { DocumentScanner scanner = new DocumentScanner(); // Scan only (for audit purposes) ScanResult result = scanner.ScanDocument("application-form.pdf"); var summary = result.GetSummary(); // Scan and redact in one operation scanner.ScanAndRedact("application-form.pdf", "application-form-redacted.pdf"); }}
using IronPdf;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Linq;
public class SensitiveDataMatch
{
public string PatternType { get; set; }
public string Value { get; set; }
public int PageNumber { get; set; }
}
public class ScanResult
{
public string FilePath { get; set; }
public List<SensitiveDataMatch> Matches { get; set; } = new List<SensitiveDataMatch>();
public bool ContainsSensitiveData => Matches.Count > 0;
public Dictionary<string, int> GetSummary()
{
return Matches.GroupBy(m => m.PatternType)
.ToDictionary(g => g.Key, g => g.Count());
}
}
public class DocumentScanner
{
private readonly Dictionary<string, string> _patterns;
public DocumentScanner()
{
_patterns = new Dictionary<string, string>
{
{ "Social Security Number", @"\b\d{3}-\d{2}-\d{4}\b" },
{ "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
{ "Email Address", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
{ "Phone Number", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" },
{ "Date of Birth Pattern", @"\b(?:DOB|Date of Birth|Birth Date)[:\s]+\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" }
};
}
public ScanResult ScanDocument(string filePath)
{
ScanResult result = new ScanResult { FilePath = filePath };
PdfDocument pdf = PdfDocument.FromFile(filePath);
// Scan each page individually to track location
for (int pageIndex = 0; pageIndex < pdf.PageCount; pageIndex++)
{
string pageText = pdf.ExtractTextFromPage(pageIndex);
foreach (var pattern in _patterns)
{
Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(pageText);
foreach (Match match in matches)
{
result.Matches.Add(new SensitiveDataMatch
{
PatternType = pattern.Key,
Value = MaskValue(match.Value, pattern.Key),
PageNumber = pageIndex + 1
});
}
}
}
return result;
}
// Partially mask values for safe storage
private string MaskValue(string value, string patternType)
{
if (patternType == "Social Security Number" && value.Length >= 4)
{
return "XXX-XX-" + value.Substring(value.Length - 4);
}
if (patternType == "Credit Card" && value.Length >= 4)
{
return "****-****-****-" + value.Substring(value.Length - 4);
}
if (patternType == "Email Address")
{
int atIndex = value.IndexOf('@');
if (atIndex > 2)
{
return value.Substring(0, 2) + "***" + value.Substring(atIndex);
}
}
return value.Length > 4 ? value.Substring(0, 2) + "***" : "****";
}
public void ScanAndRedact(string inputPath, string outputPath)
{
// First scan to identify sensitive data
ScanResult scanResult = ScanDocument(inputPath);
if (!scanResult.ContainsSensitiveData)
{
return;
}
// Load document for redaction
PdfDocument pdf = PdfDocument.FromFile(inputPath);
// Extract unique actual values (not masked) for redaction
string fullText = pdf.ExtractAllText();
HashSet<string> valuesToRedact = new HashSet<string>();
foreach (var pattern in _patterns)
{
Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
foreach (Match match in regex.Matches(fullText))
{
valuesToRedact.Add(match.Value);
}
}
// Apply redactions
foreach (string value in valuesToRedact)
{
pdf.RedactTextOnAllPages(value);
}
pdf.SaveAs(outputPath);
}
}
// Usage
class Program
{
static void Main()
{
DocumentScanner scanner = new DocumentScanner();
// Scan only (for audit purposes)
ScanResult result = scanner.ScanDocument("application-form.pdf");
var summary = result.GetSummary();
// Scan and redact in one operation
scanner.ScanAndRedact("application-form.pdf", "application-form-redacted.pdf");
}
}
ImportsIronPdfImportsSystem.Collections.GenericImportsSystem.Text.RegularExpressionsImportsSystem.LinqPublic Class SensitiveDataMatch Public Property PatternTypeAsString Public Property ValueAsString Public Property PageNumberAsIntegerEnd ClassPublic Class ScanResult Public Property FilePathAsString Public Property MatchesAsList(OfSensitiveDataMatch) = New List(OfSensitiveDataMatch)() PublicReadOnlyPropertyContainsSensitiveDataAsBoolean Get ReturnMatches.Count > 0End Get End Property Public Function GetSummary() AsDictionary(OfString, Integer) ReturnMatches.GroupBy(Function(m) m.PatternType) _ .ToDictionary(Function(g) g.Key, Function(g) g.Count()) End FunctionEnd ClassPublic Class DocumentScanner PrivateReadOnly _patterns AsDictionary(OfString, String) Public Sub New() _patterns = New Dictionary(OfString, String) From { {"Social Security Number", "\b\d{3}-\d{2}-\d{4}\b"}, {"Credit Card", "\b(?:\d{4}[-\s]?){3}\d{1,4}\b"}, {"Email Address", "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"}, {"Phone Number", "\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b"}, {"Date of Birth Pattern", "\b(?:DOB|Date of Birth|Birth Date)[:\s]+\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b"} } End Sub Public Function ScanDocument(filePath AsString) AsScanResult Dim result As New ScanResultWith {.FilePath = filePath} Dim pdf AsPdfDocument = PdfDocument.FromFile(filePath) ' Scan each page individually to track location For pageIndex AsInteger = 0 To pdf.PageCount - 1 Dim pageText AsString = pdf.ExtractTextFromPage(pageIndex) For Each pattern In _patterns Dim regex As New Regex(pattern.Value, RegexOptions.IgnoreCase) Dim matches AsMatchCollection = regex.Matches(pageText) For Each match AsMatchIn matches result.Matches.Add(New SensitiveDataMatchWith { .PatternType = pattern.Key, .Value = MaskValue(match.Value, pattern.Key), .PageNumber = pageIndex + 1 }) Next Next Next Return result End Function ' Partially mask values for safe storage Private Function MaskValue(value AsString, patternType AsString) AsString If patternType = "Social Security Number"AndAlso value.Length >= 4 Then Return "XXX-XX-" & value.Substring(value.Length - 4) End If If patternType = "Credit Card"AndAlso value.Length >= 4 Then Return "****-****-****-" & value.Substring(value.Length - 4) End If If patternType = "Email Address" Then Dim atIndex AsInteger = value.IndexOf("@"c) If atIndex > 2 Then Return value.Substring(0, 2) & "***" & value.Substring(atIndex) End If End If Return If(value.Length > 4, value.Substring(0, 2) & "***", "****") End Function Public Sub ScanAndRedact(inputPath AsString, outputPath AsString) ' First scan to identify sensitive data Dim scanResult AsScanResult = ScanDocument(inputPath) IfNot scanResult.ContainsSensitiveDataThen Return End If ' Load document for redaction Dim pdf AsPdfDocument = PdfDocument.FromFile(inputPath) ' Extract unique actual values (not masked) for redaction Dim fullText AsString = pdf.ExtractAllText() Dim valuesToRedact As New HashSet(OfString)() For Each pattern In _patterns Dim regex As New Regex(pattern.Value, RegexOptions.IgnoreCase) For Each match AsMatchIn regex.Matches(fullText) valuesToRedact.Add(match.Value) Next Next ' Apply redactions For Each value AsStringIn valuesToRedact pdf.RedactTextOnAllPages(value) Next pdf.SaveAs(outputPath) End SubEnd Class' UsageModuleProgram Sub Main() Dim scanner As New DocumentScanner() ' Scan only (for audit purposes) Dim result AsScanResult = scanner.ScanDocument("application-form.pdf") Dim summary = result.GetSummary() ' Scan and redact in one operation scanner.ScanAndRedact("application-form.pdf", "application-form-redacted.pdf") End SubEndModule
Imports IronPdf
Imports System.Collections.Generic
Imports System.Text.RegularExpressions
Imports System.Linq
Public Class SensitiveDataMatch
Public Property PatternType As String
Public Property Value As String
Public Property PageNumber As Integer
End Class
Public Class ScanResult
Public Property FilePath As String
Public Property Matches As List(Of SensitiveDataMatch) = New List(Of SensitiveDataMatch)()
Public ReadOnly Property ContainsSensitiveData As Boolean
Get
Return Matches.Count > 0
End Get
End Property
Public Function GetSummary() As Dictionary(Of String, Integer)
Return Matches.GroupBy(Function(m) m.PatternType) _
.ToDictionary(Function(g) g.Key, Function(g) g.Count())
End Function
End Class
Public Class DocumentScanner
Private ReadOnly _patterns As Dictionary(Of String, String)
Public Sub New()
_patterns = New Dictionary(Of String, String) From {
{"Social Security Number", "\b\d{3}-\d{2}-\d{4}\b"},
{"Credit Card", "\b(?:\d{4}[-\s]?){3}\d{1,4}\b"},
{"Email Address", "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"},
{"Phone Number", "\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b"},
{"Date of Birth Pattern", "\b(?:DOB|Date of Birth|Birth Date)[:\s]+\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b"}
}
End Sub
Public Function ScanDocument(filePath As String) As ScanResult
Dim result As New ScanResult With {.FilePath = filePath}
Dim pdf As PdfDocument = PdfDocument.FromFile(filePath)
' Scan each page individually to track location
For pageIndex As Integer = 0 To pdf.PageCount - 1
Dim pageText As String = pdf.ExtractTextFromPage(pageIndex)
For Each pattern In _patterns
Dim regex As New Regex(pattern.Value, RegexOptions.IgnoreCase)
Dim matches As MatchCollection = regex.Matches(pageText)
For Each match As Match In matches
result.Matches.Add(New SensitiveDataMatch With {
.PatternType = pattern.Key,
.Value = MaskValue(match.Value, pattern.Key),
.PageNumber = pageIndex + 1
})
Next
Next
Next
Return result
End Function
' Partially mask values for safe storage
Private Function MaskValue(value As String, patternType As String) As String
If patternType = "Social Security Number" AndAlso value.Length >= 4 Then
Return "XXX-XX-" & value.Substring(value.Length - 4)
End If
If patternType = "Credit Card" AndAlso value.Length >= 4 Then
Return "****-****-****-" & value.Substring(value.Length - 4)
End If
If patternType = "Email Address" Then
Dim atIndex As Integer = value.IndexOf("@"c)
If atIndex > 2 Then
Return value.Substring(0, 2) & "***" & value.Substring(atIndex)
End If
End If
Return If(value.Length > 4, value.Substring(0, 2) & "***", "****")
End Function
Public Sub ScanAndRedact(inputPath As String, outputPath As String)
' First scan to identify sensitive data
Dim scanResult As ScanResult = ScanDocument(inputPath)
If Not scanResult.ContainsSensitiveData Then
Return
End If
' Load document for redaction
Dim pdf As PdfDocument = PdfDocument.FromFile(inputPath)
' Extract unique actual values (not masked) for redaction
Dim fullText As String = pdf.ExtractAllText()
Dim valuesToRedact As New HashSet(Of String)()
For Each pattern In _patterns
Dim regex As New Regex(pattern.Value, RegexOptions.IgnoreCase)
For Each match As Match In regex.Matches(fullText)
valuesToRedact.Add(match.Value)
Next
Next
' Apply redactions
For Each value As String In valuesToRedact
pdf.RedactTextOnAllPages(value)
Next
pdf.SaveAs(outputPath)
End Sub
End Class
' Usage
Module Program
Sub Main()
Dim scanner As New DocumentScanner()
' Scan only (for audit purposes)
Dim result As ScanResult = scanner.ScanDocument("application-form.pdf")
Dim summary = result.GetSummary()
' Scan and redact in one operation
scanner.ScanAndRedact("application-form.pdf", "application-form-redacted.pdf")
End Sub
End Module
Skaner zapewnia wgląd w to, jakie informacje poufne istnieją, zanim nastąpią jakiekolwiek modyfikacje. Wspiera to procesy zapewniania zgodności, w których wymagana jest dokumentacja tego, co zostało znalezione i usunięte. Funkcja maskowania gwarantuje, że pliki dziennika i raporty same w sobie nie staną się źródłem ujawnienia danych.
Jak zamazać określone obszary w pliku PDF?
Cenzurowanie tekstu skutecznie odnosi się do treści opartej na znakach, ale PDF-y często zawierają poufne informacje w formach, które dopasowanie tekstu nie może obsłużyć. Podpisy, zdjęcia, odręczne adnotacje, pieczątki i elementy graficzne wymagają innego podejścia. Redakcja oparta na regionach pozwala określić prostokątne obszary przez ich współrzędne i trwale zaciemnić wszystko w ich granicach.
IronPDF używa struktury RectangleF do definiowania regionów redagowania. Należy określić współrzędne X i Y lewego górnego rogu, a następnie szerokość i wysokość obszaru. Współrzędne są mierzone w punktach od lewego dolnego rogu strony, co odpowiada układowi współrzędnych specyfikacji PDF.
Wejscie
Podpisany dokument umowy zawierający odręczne podpisy oraz zdjęcie dokumentu tożsamości, które należy zamazać przy użyciu funkcji zamazywania obszarów na podstawie współrzędnych.
using IronPdf;using IronSoftware.Drawing;// Load a document with signature blocks and photosPdfDocument pdf = PdfDocument.FromFile("signed-agreement.pdf");// Define a region for a signature block// Located 100 points from left, 650 points from bottom// Width of 200 points, height of 50 pointsRectangleF signatureRegion = new RectangleF(100, 650, 200, 50);// Redact the signature region on all pagespdf.RedactRegionsOnAllPages(signatureRegion);// Define a region for a photo ID in the upper rightRectangleF photoRegion = new RectangleF(450, 700, 100, 120);pdf.RedactRegionsOnAllPages(photoRegion);// Save the document with regions redactedpdf.SaveAs("signed-agreement-redacted.pdf");
using IronPdf;
using IronSoftware.Drawing;
// Load a document with signature blocks and photos
PdfDocument pdf = PdfDocument.FromFile("signed-agreement.pdf");
// Define a region for a signature block
// Located 100 points from left, 650 points from bottom
// Width of 200 points, height of 50 points
RectangleF signatureRegion = new RectangleF(100, 650, 200, 50);
// Redact the signature region on all pages
pdf.RedactRegionsOnAllPages(signatureRegion);
// Define a region for a photo ID in the upper right
RectangleF photoRegion = new RectangleF(450, 700, 100, 120);
pdf.RedactRegionsOnAllPages(photoRegion);
// Save the document with regions redacted
pdf.SaveAs("signed-agreement-redacted.pdf");
ImportsIronPdfImportsIronSoftware.Drawing' Load a document with signature blocks and photosDim pdf AsPdfDocument = PdfDocument.FromFile("signed-agreement.pdf")' Define a region for a signature block' Located 100 points from left, 650 points from bottom' Width of 200 points, height of 50 pointsDim signatureRegion As New RectangleF(100, 650, 200, 50)' Redact the signature region on all pagespdf.RedactRegionsOnAllPages(signatureRegion)' Define a region for a photo ID in the upper rightDim photoRegion As New RectangleF(450, 700, 100, 120)pdf.RedactRegionsOnAllPages(photoRegion)' Save the document with regions redactedpdf.SaveAs("signed-agreement-redacted.pdf")
Imports IronPdf
Imports IronSoftware.Drawing
' Load a document with signature blocks and photos
Dim pdf As PdfDocument = PdfDocument.FromFile("signed-agreement.pdf")
' Define a region for a signature block
' Located 100 points from left, 650 points from bottom
' Width of 200 points, height of 50 points
Dim signatureRegion As New RectangleF(100, 650, 200, 50)
' Redact the signature region on all pages
pdf.RedactRegionsOnAllPages(signatureRegion)
' Define a region for a photo ID in the upper right
Dim photoRegion As New RectangleF(450, 700, 100, 120)
pdf.RedactRegionsOnAllPages(photoRegion)
' Save the document with regions redacted
pdf.SaveAs("signed-agreement-redacted.pdf")
Ten kod używa struktur RectangleF do definiowania prostokątnych obszarów do redagowania. Obszar podpisu znajduje się we współrzędnych (100, 650) i ma wymiary 200 x 50 pikseli, natomiast obszar zdjęcia znajduje się we współrzędnych (450, 700) i ma wymiary 100 x 120 pikseli. Metoda RedactRegionsOnAllPages stosuje czarne prostokąty nad tymi regionami na wszystkich stronach.
Przykładowy Wynik
Określenie prawidłowych współrzędnych często wymaga pewnych eksperymentów lub pomiarów. Strony PDF zazwyczaj wykorzystują układ współrzędnych, w którym jeden punkt odpowiada 1/72 cała. Standardowa strona formatu US Letter ma szerokość 612 punktów i wysokość 792 punktów. Strony formatu A4 mają wymiary około 595 na 842 punktów. Pomocne mogą być narzędzia do przeglądania plików PDF, które wyświetlają współrzędne podczas przesuwania kursora, lub można programowo wyodrębnić wymiary strony:
using IronPdf;using IronSoftware.Drawing;PdfDocument pdf = PdfDocument.FromFile("form-document.pdf");// Get dimensions of the first pagevar pageInfo = pdf.Pages[0];// Calculate regions relative to page dimensions// Redact the bottom quarter of the page where signatures appearfloat signatureAreaHeight = (float)(pageInfo.Height / 4);RectangleF bottomQuarter = new RectangleF( 0, // Start at left edge 0, // Start at bottom (float)pageInfo.Width, // Full page width signatureAreaHeight // Quarter of page height);pdf.RedactRegionsOnAllPages(bottomQuarter);// Redact a header area at the top containing letterhead with addressfloat headerHeight = 100;RectangleF headerArea = new RectangleF( 0, (float)(pageInfo.Height - headerHeight), // Position from bottom (float)pageInfo.Width, headerHeight);pdf.RedactRegionsOnAllPages(headerArea);pdf.SaveAs("form-document-redacted.pdf");
using IronPdf;
using IronSoftware.Drawing;
PdfDocument pdf = PdfDocument.FromFile("form-document.pdf");
// Get dimensions of the first page
var pageInfo = pdf.Pages[0];
// Calculate regions relative to page dimensions
// Redact the bottom quarter of the page where signatures appear
float signatureAreaHeight = (float)(pageInfo.Height / 4);
RectangleF bottomQuarter = new RectangleF(
0, // Start at left edge
0, // Start at bottom
(float)pageInfo.Width, // Full page width
signatureAreaHeight // Quarter of page height
);
pdf.RedactRegionsOnAllPages(bottomQuarter);
// Redact a header area at the top containing letterhead with address
float headerHeight = 100;
RectangleF headerArea = new RectangleF(
0,
(float)(pageInfo.Height - headerHeight), // Position from bottom
(float)pageInfo.Width,
headerHeight
);
pdf.RedactRegionsOnAllPages(headerArea);
pdf.SaveAs("form-document-redacted.pdf");
ImportsIronPdfImportsIronSoftware.DrawingDim pdf AsPdfDocument = PdfDocument.FromFile("form-document.pdf")' Get dimensions of the first pageDim pageInfo = pdf.Pages(0)' Calculate regions relative to page dimensions' Redact the bottom quarter of the page where signatures appearDim signatureAreaHeight AsSingle = CSng(pageInfo.Height / 4)Dim bottomQuarter As New RectangleF(0, 0, CSng(pageInfo.Width), signatureAreaHeight)pdf.RedactRegionsOnAllPages(bottomQuarter)' Redact a header area at the top containing letterhead with addressDim headerHeight AsSingle = 100Dim headerArea As New RectangleF(0, CSng(pageInfo.Height - headerHeight), CSng(pageInfo.Width), headerHeight)pdf.RedactRegionsOnAllPages(headerArea)pdf.SaveAs("form-document-redacted.pdf")
Imports IronPdf
Imports IronSoftware.Drawing
Dim pdf As PdfDocument = PdfDocument.FromFile("form-document.pdf")
' Get dimensions of the first page
Dim pageInfo = pdf.Pages(0)
' Calculate regions relative to page dimensions
' Redact the bottom quarter of the page where signatures appear
Dim signatureAreaHeight As Single = CSng(pageInfo.Height / 4)
Dim bottomQuarter As New RectangleF(0, 0, CSng(pageInfo.Width), signatureAreaHeight)
pdf.RedactRegionsOnAllPages(bottomQuarter)
' Redact a header area at the top containing letterhead with address
Dim headerHeight As Single = 100
Dim headerArea As New RectangleF(0, CSng(pageInfo.Height - headerHeight), CSng(pageInfo.Width), headerHeight)
pdf.RedactRegionsOnAllPages(headerArea)
pdf.SaveAs("form-document-redacted.pdf")
Moją ulubioną biblioteką tego typu jest IronPDF. Umożliwia ona szybkie i efektywne manipulowanie plikami PDF. Posiada także wiele cennych funkcji, takich jak eksport do formatu PDF/A i cyfrowe podpisywanie dokumentów PDF.
IronOCR pozwala nam oszczędzić 40 000 USD rocznie na ręcznym przetwarzaniu, jednocześnie zwiększając produktywność i uwalniając zasoby do zadań o wysokim wpływie. Gorąco polecam.
IronSuite odgrywa kluczową rolę w naszej działalności. Są to narzędzia zwiększające wydajność w całej firmie, w tym tworzenie planów pięter i poprawa zarządzania zapasami.
Jak mogę zredagować wiele obszarów na różnych stronach?
Złożone dokumenty często wymagają usunięcia różnych fragmentów na różnych stronach. Formularz wielostronicowy może zawierać linie podpisu w różnych pozycjach, a różne strony mogą zawierać zdjęcia, pieczęcie lub inne elementy graficzne w unikalnych miejscach. IronPDF zawiera metody specyficzne dla stron do ukierunkowanej redakcji regionów.
using IronPdf;using IronSoftware.Drawing;PdfDocument pdf = PdfDocument.FromFile("multi-page-application.pdf");// Define page-specific redaction regions// Page 1: Cover page with applicant photoRectangleF page1Photo = new RectangleF(450, 600, 120, 150);pdf.RedactRegionOnPage(0, page1Photo);// Page 2: Personal information sectionRectangleF page2InfoBlock = new RectangleF(50, 400, 250, 200);pdf.RedactRegionOnPage(1, page2InfoBlock);// Pages 3-5: Signature lines at the same positionRectangleF signatureLine = new RectangleF(100, 100, 200, 40);int[] signaturePages = { 2, 3, 4 };pdf.RedactRegionOnPages(signaturePages, signatureLine);// Page 6: Multiple regions - notary stamp and witness signatureRectangleF notaryStamp = new RectangleF(400, 150, 150, 150);RectangleF witnessSignature = new RectangleF(100, 150, 200, 40);pdf.RedactRegionOnPage(5, notaryStamp);pdf.RedactRegionOnPage(5, witnessSignature);pdf.SaveAs("multi-page-application-redacted.pdf");
using IronPdf;
using IronSoftware.Drawing;
PdfDocument pdf = PdfDocument.FromFile("multi-page-application.pdf");
// Define page-specific redaction regions
// Page 1: Cover page with applicant photo
RectangleF page1Photo = new RectangleF(450, 600, 120, 150);
pdf.RedactRegionOnPage(0, page1Photo);
// Page 2: Personal information section
RectangleF page2InfoBlock = new RectangleF(50, 400, 250, 200);
pdf.RedactRegionOnPage(1, page2InfoBlock);
// Pages 3-5: Signature lines at the same position
RectangleF signatureLine = new RectangleF(100, 100, 200, 40);
int[] signaturePages = { 2, 3, 4 };
pdf.RedactRegionOnPages(signaturePages, signatureLine);
// Page 6: Multiple regions - notary stamp and witness signature
RectangleF notaryStamp = new RectangleF(400, 150, 150, 150);
RectangleF witnessSignature = new RectangleF(100, 150, 200, 40);
pdf.RedactRegionOnPage(5, notaryStamp);
pdf.RedactRegionOnPage(5, witnessSignature);
pdf.SaveAs("multi-page-application-redacted.pdf");
ImportsIronPdfImportsIronSoftware.DrawingDim pdf AsPdfDocument = PdfDocument.FromFile("multi-page-application.pdf")' Define page-specific redaction regions' Page 1: Cover page with applicant photoDim page1Photo As New RectangleF(450, 600, 120, 150)pdf.RedactRegionOnPage(0, page1Photo)' Page 2: Personal information sectionDim page2InfoBlock As New RectangleF(50, 400, 250, 200)pdf.RedactRegionOnPage(1, page2InfoBlock)' Pages 3-5: Signature lines at the same positionDim signatureLine As New RectangleF(100, 100, 200, 40)Dim signaturePages AsInteger() = {2, 3, 4}pdf.RedactRegionOnPages(signaturePages, signatureLine)' Page 6: Multiple regions - notary stamp and witness signatureDim notaryStamp As New RectangleF(400, 150, 150, 150)Dim witnessSignature As New RectangleF(100, 150, 200, 40)pdf.RedactRegionOnPage(5, notaryStamp)pdf.RedactRegionOnPage(5, witnessSignature)pdf.SaveAs("multi-page-application-redacted.pdf")
Imports IronPdf
Imports IronSoftware.Drawing
Dim pdf As PdfDocument = PdfDocument.FromFile("multi-page-application.pdf")
' Define page-specific redaction regions
' Page 1: Cover page with applicant photo
Dim page1Photo As New RectangleF(450, 600, 120, 150)
pdf.RedactRegionOnPage(0, page1Photo)
' Page 2: Personal information section
Dim page2InfoBlock As New RectangleF(50, 400, 250, 200)
pdf.RedactRegionOnPage(1, page2InfoBlock)
' Pages 3-5: Signature lines at the same position
Dim signatureLine As New RectangleF(100, 100, 200, 40)
Dim signaturePages As Integer() = {2, 3, 4}
pdf.RedactRegionOnPages(signaturePages, signatureLine)
' Page 6: Multiple regions - notary stamp and witness signature
Dim notaryStamp As New RectangleF(400, 150, 150, 150)
Dim witnessSignature As New RectangleF(100, 150, 200, 40)
pdf.RedactRegionOnPage(5, notaryStamp)
pdf.RedactRegionOnPage(5, witnessSignature)
pdf.SaveAs("multi-page-application-redacted.pdf")
Dokumenty o spójnym układzie korzystają z definicji regionów wielokrotnego użytku:
using IronPdf;using IronSoftware.Drawing;public class FormRegions{ // Standard form regions based on common templates public static RectangleFHeaderLogo => new RectangleF(20, 720, 150, 60); public static RectangleFSignatureBlock => new RectangleF(72, 72, 200, 50); public static RectangleFDateField => new RectangleF(400, 72, 120, 20); public static RectangleFPhotoId => new RectangleF(480, 650, 100, 130); public static RectangleFAddressBlock => new RectangleF(72, 600, 250, 80);}class Program{ static voidMain() { PdfDocument pdf = PdfDocument.FromFile("standard-form.pdf"); // Apply standard redactions using predefined regions pdf.RedactRegionsOnAllPages(FormRegions.SignatureBlock); pdf.RedactRegionsOnAllPages(FormRegions.DateField); pdf.RedactRegionOnPage(0, FormRegions.PhotoId); pdf.SaveAs("standard-form-redacted.pdf"); }}
using IronPdf;
using IronSoftware.Drawing;
public class FormRegions
{
// Standard form regions based on common templates
public static RectangleF HeaderLogo => new RectangleF(20, 720, 150, 60);
public static RectangleF SignatureBlock => new RectangleF(72, 72, 200, 50);
public static RectangleF DateField => new RectangleF(400, 72, 120, 20);
public static RectangleF PhotoId => new RectangleF(480, 650, 100, 130);
public static RectangleF AddressBlock => new RectangleF(72, 600, 250, 80);
}
class Program
{
static void Main()
{
PdfDocument pdf = PdfDocument.FromFile("standard-form.pdf");
// Apply standard redactions using predefined regions
pdf.RedactRegionsOnAllPages(FormRegions.SignatureBlock);
pdf.RedactRegionsOnAllPages(FormRegions.DateField);
pdf.RedactRegionOnPage(0, FormRegions.PhotoId);
pdf.SaveAs("standard-form-redacted.pdf");
}
}
C#
Jak usunąć metadane, które mogą ujawnić poufne informacje?
Metadane plików PDF stanowią często pomijane źródło wycieku informacji. Każdy plik PDF zawiera właściwości, które mogą ujawniać poufne informacje: nazwisko autora i nazwę użytkownika, oprogramowanie użyte do utworzenia dokumentu, znaczniki czasu utworzenia i modyfikacji, oryginalną nazwę pliku, historię zmian oraz właściwości niestandardowe dodane przez różne aplikacje. Przed udostępnieniem dokumentów na zewnątrz konieczne jest usunięcie lub oczyszczenie tych metadanych. Aby uzyskać kompleksowy przegląd operacji związanych z metadanymi, zapoznaj się z naszym przewodnikiem dotyczącym metadanych.
IronPDF ujawnia metadane dokumentu poprzez właściwość MetaData, pozwalającą na odczytywanie, modyfikowanie lub całkowite usuwanie istniejących wartości.
using IronPdf;using System;// Load a document containing sensitive metadataPdfDocument pdf = PdfDocument.FromFile("internal-report.pdf");// Access current metadata propertiesstring author = pdf.MetaData.Author;string title = pdf.MetaData.Title;string subject = pdf.MetaData.Subject;string keywords = pdf.MetaData.Keywords;string creator = pdf.MetaData.Creator;string producer = pdf.MetaData.Producer;DateTime? creationDate = pdf.MetaData.CreationDate;DateTime? modifiedDate = pdf.MetaData.ModifiedDate;// Get all metadata keys including custom propertiesvar allKeys = pdf.MetaData.Keys();
using IronPdf;
using System;
// Load a document containing sensitive metadata
PdfDocument pdf = PdfDocument.FromFile("internal-report.pdf");
// Access current metadata properties
string author = pdf.MetaData.Author;
string title = pdf.MetaData.Title;
string subject = pdf.MetaData.Subject;
string keywords = pdf.MetaData.Keywords;
string creator = pdf.MetaData.Creator;
string producer = pdf.MetaData.Producer;
DateTime? creationDate = pdf.MetaData.CreationDate;
DateTime? modifiedDate = pdf.MetaData.ModifiedDate;
// Get all metadata keys including custom properties
var allKeys = pdf.MetaData.Keys();
ImportsIronPdfImportsSystem' Load a document containing sensitive metadataDim pdf AsPdfDocument = PdfDocument.FromFile("internal-report.pdf")' Access current metadata propertiesDim author AsString = pdf.MetaData.AuthorDim title AsString = pdf.MetaData.TitleDim subject AsString = pdf.MetaData.SubjectDim keywords AsString = pdf.MetaData.KeywordsDim creator AsString = pdf.MetaData.CreatorDim producer AsString = pdf.MetaData.ProducerDim creationDate AsDateTime? = pdf.MetaData.CreationDateDim modifiedDate AsDateTime? = pdf.MetaData.ModifiedDate' Get all metadata keys including custom propertiesDim allKeys = pdf.MetaData.Keys()
Imports IronPdf
Imports System
' Load a document containing sensitive metadata
Dim pdf As PdfDocument = PdfDocument.FromFile("internal-report.pdf")
' Access current metadata properties
Dim author As String = pdf.MetaData.Author
Dim title As String = pdf.MetaData.Title
Dim subject As String = pdf.MetaData.Subject
Dim keywords As String = pdf.MetaData.Keywords
Dim creator As String = pdf.MetaData.Creator
Dim producer As String = pdf.MetaData.Producer
Dim creationDate As DateTime? = pdf.MetaData.CreationDate
Dim modifiedDate As DateTime? = pdf.MetaData.ModifiedDate
' Get all metadata keys including custom properties
Dim allKeys = pdf.MetaData.Keys()
Aby usunąć wrażliwe metadane przed dystrybucją:
Wejscie
Wewnętrzna notatka zawierająca osadzone metadane, takie jak nazwiska autorów, znaczniki czasu utworzenia oraz niestandardowe właściwości, które mogą ujawniać poufne informacje organizacyjne.
using IronPdf;using System;PdfDocument pdf = PdfDocument.FromFile("confidential-memo.pdf");// Replace identifying metadata with generic valuespdf.MetaData.Author = "Organization Name";pdf.MetaData.Creator = "Document System";pdf.MetaData.Producer = "";pdf.MetaData.Title = "Public Document";pdf.MetaData.Subject = "";pdf.MetaData.Keywords = "";// Normalize dates to remove timing informationpdf.MetaData.CreationDate = DateTime.Now;pdf.MetaData.ModifiedDate = DateTime.Now;// Remove specific custom metadata keyspdf.MetaData.RemoveMetaDataKey("OriginalFilename");pdf.MetaData.RemoveMetaDataKey("LastSavedBy");pdf.MetaData.RemoveMetaDataKey("Company");pdf.MetaData.RemoveMetaDataKey("Manager");// Remove custom properties added by applicationstry{ pdf.MetaData.CustomProperties.Remove("SourcePath");}catch { }pdf.SaveAs("confidential-memo-cleaned.pdf");
using IronPdf;
using System;
PdfDocument pdf = PdfDocument.FromFile("confidential-memo.pdf");
// Replace identifying metadata with generic values
pdf.MetaData.Author = "Organization Name";
pdf.MetaData.Creator = "Document System";
pdf.MetaData.Producer = "";
pdf.MetaData.Title = "Public Document";
pdf.MetaData.Subject = "";
pdf.MetaData.Keywords = "";
// Normalize dates to remove timing information
pdf.MetaData.CreationDate = DateTime.Now;
pdf.MetaData.ModifiedDate = DateTime.Now;
// Remove specific custom metadata keys
pdf.MetaData.RemoveMetaDataKey("OriginalFilename");
pdf.MetaData.RemoveMetaDataKey("LastSavedBy");
pdf.MetaData.RemoveMetaDataKey("Company");
pdf.MetaData.RemoveMetaDataKey("Manager");
// Remove custom properties added by applications
try
{
pdf.MetaData.CustomProperties.Remove("SourcePath");
}
catch { }
pdf.SaveAs("confidential-memo-cleaned.pdf");
ImportsIronPdfImportsSystemDim pdf AsPdfDocument = PdfDocument.FromFile("confidential-memo.pdf")' Replace identifying metadata with generic valuespdf.MetaData.Author = "Organization Name"pdf.MetaData.Creator = "Document System"pdf.MetaData.Producer = ""pdf.MetaData.Title = "Public Document"pdf.MetaData.Subject = ""pdf.MetaData.Keywords = ""' Normalize dates to remove timing informationpdf.MetaData.CreationDate = DateTime.Nowpdf.MetaData.ModifiedDate = DateTime.Now' Remove specific custom metadata keyspdf.MetaData.RemoveMetaDataKey("OriginalFilename")pdf.MetaData.RemoveMetaDataKey("LastSavedBy")pdf.MetaData.RemoveMetaDataKey("Company")pdf.MetaData.RemoveMetaDataKey("Manager")' Remove custom properties added by applicationsTry pdf.MetaData.CustomProperties.Remove("SourcePath")CatchEndTrypdf.SaveAs("confidential-memo-cleaned.pdf")
Imports IronPdf
Imports System
Dim pdf As PdfDocument = PdfDocument.FromFile("confidential-memo.pdf")
' Replace identifying metadata with generic values
pdf.MetaData.Author = "Organization Name"
pdf.MetaData.Creator = "Document System"
pdf.MetaData.Producer = ""
pdf.MetaData.Title = "Public Document"
pdf.MetaData.Subject = ""
pdf.MetaData.Keywords = ""
' Normalize dates to remove timing information
pdf.MetaData.CreationDate = DateTime.Now
pdf.MetaData.ModifiedDate = DateTime.Now
' Remove specific custom metadata keys
pdf.MetaData.RemoveMetaDataKey("OriginalFilename")
pdf.MetaData.RemoveMetaDataKey("LastSavedBy")
pdf.MetaData.RemoveMetaDataKey("Company")
pdf.MetaData.RemoveMetaDataKey("Manager")
' Remove custom properties added by applications
Try
pdf.MetaData.CustomProperties.Remove("SourcePath")
Catch
End Try
pdf.SaveAs("confidential-memo-cleaned.pdf")
Ten kod zastępuje identyfikujące pola metadanych wartościami ogólnymi, normalizuje znaczniki czasu do bieżącej daty oraz usuwa niestandardowe klucze metadanych, które mogły zostać dodane przez aplikacje. Metoda RemoveMetaDataKey celuje w określone właściwości jak "OryginalnaNazwaPliku" i "OstatnioZapisanePrzez", które mogą ujawniać wewnętrzne informacje.
Przykładowy Wynik
Dokładne czyszczenie metadanych w operacjach wsadowych wymaga systematycznego podejścia:
using IronPdf;using System;using System.Collections.Generic;public class MetadataCleaner{ private readonly string _defaultAuthor; private readonly string _defaultCreator; publicMetadataCleaner(string organizationName) { _defaultAuthor = organizationName; _defaultCreator = $"{organizationName} Document System"; } public voidCleanMetadata(PdfDocument pdf) { // Replace standard metadata fields pdf.MetaData.Author = _defaultAuthor; pdf.MetaData.Creator = _defaultCreator; pdf.MetaData.Producer = ""; pdf.MetaData.Subject = ""; pdf.MetaData.Keywords = ""; // Normalize timestamps DateTime now = DateTime.Now; pdf.MetaData.CreationDate = now; pdf.MetaData.ModifiedDate = now; // Get all keys and remove potentially sensitive ones List<string> keysToRemove = new List<string>(); foreach (string key in pdf.MetaData.Keys()) { // Keep only essential keys if (!IsEssentialKey(key)) { keysToRemove.Add(key); } } foreach (string key in keysToRemove) { pdf.MetaData.RemoveMetaDataKey(key); } } private boolIsEssentialKey(string key) { // Keep only the basic display properties string[] essentialKeys = { "Title", "Author", "CreationDate", "ModifiedDate" }; foreach (string essential in essentialKeys) { if (key.Equals(essential, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; }}// Usageclass Program{ static voidMain() { MetadataCleaner cleaner = new MetadataCleaner("Acme Corporation"); PdfDocument pdf = PdfDocument.FromFile("report.pdf"); cleaner.CleanMetadata(pdf); pdf.SaveAs("report-clean.pdf"); }}
using IronPdf;
using System;
using System.Collections.Generic;
public class MetadataCleaner
{
private readonly string _defaultAuthor;
private readonly string _defaultCreator;
public MetadataCleaner(string organizationName)
{
_defaultAuthor = organizationName;
_defaultCreator = $"{organizationName} Document System";
}
public void CleanMetadata(PdfDocument pdf)
{
// Replace standard metadata fields
pdf.MetaData.Author = _defaultAuthor;
pdf.MetaData.Creator = _defaultCreator;
pdf.MetaData.Producer = "";
pdf.MetaData.Subject = "";
pdf.MetaData.Keywords = "";
// Normalize timestamps
DateTime now = DateTime.Now;
pdf.MetaData.CreationDate = now;
pdf.MetaData.ModifiedDate = now;
// Get all keys and remove potentially sensitive ones
List<string> keysToRemove = new List<string>();
foreach (string key in pdf.MetaData.Keys())
{
// Keep only essential keys
if (!IsEssentialKey(key))
{
keysToRemove.Add(key);
}
}
foreach (string key in keysToRemove)
{
pdf.MetaData.RemoveMetaDataKey(key);
}
}
private bool IsEssentialKey(string key)
{
// Keep only the basic display properties
string[] essentialKeys = { "Title", "Author", "CreationDate", "ModifiedDate" };
foreach (string essential in essentialKeys)
{
if (key.Equals(essential, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
}
// Usage
class Program
{
static void Main()
{
MetadataCleaner cleaner = new MetadataCleaner("Acme Corporation");
PdfDocument pdf = PdfDocument.FromFile("report.pdf");
cleaner.CleanMetadata(pdf);
pdf.SaveAs("report-clean.pdf");
}
}
C#
Jak mogę oczyścić plik PDF, aby usunąć osadzone skrypty i ukryte zagrożenia?
Oczyszczanie plików PDF rozwiązuje problemy związane z bezpieczeństwem, które wykraczają poza widoczną treść i metadane. Pliki PDF mogą zawierać kod JavaScript, osadzone pliki wykonywalne, akcje formularzy wywołujące połączenia zewnętrzne oraz inne potencjalnie złośliwe elementy. Funkcje te służą uzasadnionym celom, takim jak formularze interaktywne i treści multimedialne, ale stwarzają również wektory ataku. Oczyszczanie pliku PDF usuwa te aktywne elementy, zachowując jednocześnie zawartość wizualną. Aby uzyskać dodatkowe informacje na temat metod czyszczenia danych, zapoznaj się z naszym przewodnikiem "Jak oczyścić plik PDF".
Klasa Cleaner IronPDF obsługuje zależność poprzez eleganckie podejście: przekonwertowanie PDF na format obrazu, a następnie z powrotem. Proces ten usuwa kod JavaScript, osadzone obiekty, akcje formularzy i adnotacje, zachowując jednocześnie nienaruszony wygląd strony. Biblioteka oferuje dwie metody oczyszczania o różnych właściwościach.
Wejscie
Dokument PDF otrzymany z zewnętrznego źródła, który może zawierać JavaScript, osadzone obiekty lub inne potencjalnie złośliwe treści aktywne.
using IronPdf;// Load a PDF that may contain active contentPdfDocument pdf = PdfDocument.FromFile("received-document.pdf");// Sanitize using SVG conversion// Faster processing, results in searchable text, slight layout variations possiblePdfDocument sanitizedSvg = Cleaner.SanitizeWithSvg(pdf);sanitizedSvg.SaveAs("sanitized-svg.pdf");// Sanitize using Bitmap conversion// Slower processing, text becomes image (not searchable), exact visual reproductionPdfDocument sanitizedBitmap = Cleaner.SanitizeWithBitmap(pdf);sanitizedBitmap.SaveAs("sanitized-bitmap.pdf");
using IronPdf;
// Load a PDF that may contain active content
PdfDocument pdf = PdfDocument.FromFile("received-document.pdf");
// Sanitize using SVG conversion
// Faster processing, results in searchable text, slight layout variations possible
PdfDocument sanitizedSvg = Cleaner.SanitizeWithSvg(pdf);
sanitizedSvg.SaveAs("sanitized-svg.pdf");
// Sanitize using Bitmap conversion
// Slower processing, text becomes image (not searchable), exact visual reproduction
PdfDocument sanitizedBitmap = Cleaner.SanitizeWithBitmap(pdf);
sanitizedBitmap.SaveAs("sanitized-bitmap.pdf");
ImportsIronPdf' Load a PDF that may contain active contentDim pdf AsPdfDocument = PdfDocument.FromFile("received-document.pdf")' Sanitize using SVG conversion' Faster processing, results in searchable text, slight layout variations possibleDim sanitizedSvg AsPdfDocument = Cleaner.SanitizeWithSvg(pdf)sanitizedSvg.SaveAs("sanitized-svg.pdf")' Sanitize using Bitmap conversion' Slower processing, text becomes image (not searchable), exact visual reproductionDim sanitizedBitmap AsPdfDocument = Cleaner.SanitizeWithBitmap(pdf)sanitizedBitmap.SaveAs("sanitized-bitmap.pdf")
Imports IronPdf
' Load a PDF that may contain active content
Dim pdf As PdfDocument = PdfDocument.FromFile("received-document.pdf")
' Sanitize using SVG conversion
' Faster processing, results in searchable text, slight layout variations possible
Dim sanitizedSvg As PdfDocument = Cleaner.SanitizeWithSvg(pdf)
sanitizedSvg.SaveAs("sanitized-svg.pdf")
' Sanitize using Bitmap conversion
' Slower processing, text becomes image (not searchable), exact visual reproduction
Dim sanitizedBitmap As PdfDocument = Cleaner.SanitizeWithBitmap(pdf)
sanitizedBitmap.SaveAs("sanitized-bitmap.pdf")
Ten kod pokazuje dwie metody zależności dostarczane przez klasę Cleaner IronPDF. SanitizeWithSvg konwertuje PDF przez pośredni format SVG, zachowując tekst do wyszukiwania, usuwając jednocześnie aktywną treść. SanitizeWithBitmap najpierw konwertuje strony na obrazy, produkując dokładne wizualne kopie, ale z tekstem renderowanym jako niewyszukiwalne grafiki.
Przykładowy Wynik
Metoda SVG działa szybciej i zachowuje tekst jako treść, którą można przeszukiwać, dzięki czemu nadaje się do dokumentów, które muszą pozostać zindeksowane lub dostępne. Metoda bitmapowa tworzy dokładne kopie wizualne, ale konwertuje tekst na obrazy, co uniemożliwia zaznaczanie i wyszukiwanie tekstu. Wybierz opcję zgodnie z wymaganiami dotyczącymi dokumentu docelowego.
Można również zastosować opcje renderowania podczas czyszczenia danych, aby dostosować wynik:
using IronPdf;// Load the potentially unsafe documentPdfDocument pdf = PdfDocument.FromFile("untrusted-source.pdf");// Configure rendering options for sanitizationvar renderOptions = new ChromePdfRenderOptions{MarginTop = 10,MarginBottom = 10,MarginLeft = 10,MarginRight = 10};// Sanitize with custom optionsPdfDocument sanitized = Cleaner.SanitizeWithSvg(pdf, renderOptions);sanitized.SaveAs("untrusted-source-safe.pdf");
using IronPdf;
// Load the potentially unsafe document
PdfDocument pdf = PdfDocument.FromFile("untrusted-source.pdf");
// Configure rendering options for sanitization
var renderOptions = new ChromePdfRenderOptions
{
MarginTop = 10,
MarginBottom = 10,
MarginLeft = 10,
MarginRight = 10
};
// Sanitize with custom options
PdfDocument sanitized = Cleaner.SanitizeWithSvg(pdf, renderOptions);
sanitized.SaveAs("untrusted-source-safe.pdf");
ImportsIronPdf' Load the potentially unsafe documentDim pdf AsPdfDocument = PdfDocument.FromFile("untrusted-source.pdf")' Configure rendering options for sanitizationDim renderOptions As New ChromePdfRenderOptionsWith { .MarginTop = 10, .MarginBottom = 10, .MarginLeft = 10, .MarginRight = 10}' Sanitize with custom optionsDim sanitized AsPdfDocument = Cleaner.SanitizeWithSvg(pdf, renderOptions)sanitized.SaveAs("untrusted-source-safe.pdf")
Imports IronPdf
' Load the potentially unsafe document
Dim pdf As PdfDocument = PdfDocument.FromFile("untrusted-source.pdf")
' Configure rendering options for sanitization
Dim renderOptions As New ChromePdfRenderOptions With {
.MarginTop = 10,
.MarginBottom = 10,
.MarginLeft = 10,
.MarginRight = 10
}
' Sanitize with custom options
Dim sanitized As PdfDocument = Cleaner.SanitizeWithSvg(pdf, renderOptions)
sanitized.SaveAs("untrusted-source-safe.pdf")
Srodowiska o wysokim poziomie bezpieczeństwa często wymagają łączenia sanitacji z innymi środkami ochronnymi:
using IronPdf;using System;public class SecureDocumentProcessor{ public PdfDocumentProcessUntrustedDocument(string inputPath) { // Load the document PdfDocument original = PdfDocument.FromFile(inputPath); // Step 1: Sanitize to remove active content PdfDocument sanitized = Cleaner.SanitizeWithSvg(original); // Step 2: Clean metadata sanitized.MetaData.Author = "Processed Document"; sanitized.MetaData.Creator = "Secure Processor"; sanitized.MetaData.Producer = ""; sanitized.MetaData.CreationDate = DateTime.Now; sanitized.MetaData.ModifiedDate = DateTime.Now; // Remove all custom metadata foreach (string key in sanitized.MetaData.Keys()) { if (key != "Title" && key != "Author" && key != "CreationDate" && key != "ModifiedDate") { sanitized.MetaData.RemoveMetaDataKey(key); } } return sanitized; }}// Usageclass Program{ static voidMain() { SecureDocumentProcessor processor = new SecureDocumentProcessor(); PdfDocument safe = processor.ProcessUntrustedDocument("email-attachment.pdf"); safe.SaveAs("email-attachment-safe.pdf"); }}
using IronPdf;
using System;
public class SecureDocumentProcessor
{
public PdfDocument ProcessUntrustedDocument(string inputPath)
{
// Load the document
PdfDocument original = PdfDocument.FromFile(inputPath);
// Step 1: Sanitize to remove active content
PdfDocument sanitized = Cleaner.SanitizeWithSvg(original);
// Step 2: Clean metadata
sanitized.MetaData.Author = "Processed Document";
sanitized.MetaData.Creator = "Secure Processor";
sanitized.MetaData.Producer = "";
sanitized.MetaData.CreationDate = DateTime.Now;
sanitized.MetaData.ModifiedDate = DateTime.Now;
// Remove all custom metadata
foreach (string key in sanitized.MetaData.Keys())
{
if (key != "Title" && key != "Author" && key != "CreationDate" && key != "ModifiedDate")
{
sanitized.MetaData.RemoveMetaDataKey(key);
}
}
return sanitized;
}
}
// Usage
class Program
{
static void Main()
{
SecureDocumentProcessor processor = new SecureDocumentProcessor();
PdfDocument safe = processor.ProcessUntrustedDocument("email-attachment.pdf");
safe.SaveAs("email-attachment-safe.pdf");
}
}
ImportsIronPdfImportsSystemPublic Class SecureDocumentProcessor Public Function ProcessUntrustedDocument(inputPath AsString) AsPdfDocument ' Load the document Dim original AsPdfDocument = PdfDocument.FromFile(inputPath) ' Step 1: Sanitize to remove active content Dim sanitized AsPdfDocument = Cleaner.SanitizeWithSvg(original) ' Step 2: Clean metadata sanitized.MetaData.Author = "Processed Document" sanitized.MetaData.Creator = "Secure Processor" sanitized.MetaData.Producer = "" sanitized.MetaData.CreationDate = DateTime.Now sanitized.MetaData.ModifiedDate = DateTime.Now ' Remove all custom metadata For Each key AsStringIn sanitized.MetaData.Keys() If key <> "Title"AndAlso key <> "Author"AndAlso key <> "CreationDate"AndAlso key <> "ModifiedDate" Then sanitized.MetaData.RemoveMetaDataKey(key) End If Next Return sanitized End FunctionEnd Class' UsageModuleProgram Sub Main() Dim processor As New SecureDocumentProcessor() Dim safe AsPdfDocument = processor.ProcessUntrustedDocument("email-attachment.pdf") safe.SaveAs("email-attachment-safe.pdf") End SubEndModule
Imports IronPdf
Imports System
Public Class SecureDocumentProcessor
Public Function ProcessUntrustedDocument(inputPath As String) As PdfDocument
' Load the document
Dim original As PdfDocument = PdfDocument.FromFile(inputPath)
' Step 1: Sanitize to remove active content
Dim sanitized As PdfDocument = Cleaner.SanitizeWithSvg(original)
' Step 2: Clean metadata
sanitized.MetaData.Author = "Processed Document"
sanitized.MetaData.Creator = "Secure Processor"
sanitized.MetaData.Producer = ""
sanitized.MetaData.CreationDate = DateTime.Now
sanitized.MetaData.ModifiedDate = DateTime.Now
' Remove all custom metadata
For Each key As String In sanitized.MetaData.Keys()
If key <> "Title" AndAlso key <> "Author" AndAlso key <> "CreationDate" AndAlso key <> "ModifiedDate" Then
sanitized.MetaData.RemoveMetaDataKey(key)
End If
Next
Return sanitized
End Function
End Class
' Usage
Module Program
Sub Main()
Dim processor As New SecureDocumentProcessor()
Dim safe As PdfDocument = processor.ProcessUntrustedDocument("email-attachment.pdf")
safe.SaveAs("email-attachment-safe.pdf")
End Sub
End Module
Jak przeskanować plik PDF pod kątem luk w zabezpieczeniach?
Przed przetworzeniem lub oczyszczeniem dokumentów warto ocenić, jakie potencjalne zagrożenia zawierają. Metoda Cleaner.ScanPdf IronPDF bada dokumenty przy użyciu reguł YARA, które są definicjami wzorców często używanymi w analizie złośliwego oprogramowania i wykrywaniu zagrożeń. Skanowanie identyfikuje cechy charakterystyczne dla złośliwych plików PDF.
using IronPdf;// Load the document to scanPdfDocument pdf = PdfDocument.FromFile("suspicious-document.pdf");// Scan using default YARA rulesCleanerScanResult scanResult = Cleaner.ScanPdf(pdf);// Check the scan resultsbool threatsDetected = scanResult.IsDetected;int riskCount = scanResult.Risks.Count;// Process identified risksif (scanResult.IsDetected){ foreach (var risk in scanResult.Risks) { // Handle each identified risk } // Sanitize the document before use PdfDocument sanitized = Cleaner.SanitizeWithSvg(pdf); sanitized.SaveAs("suspicious-document-safe.pdf");}
using IronPdf;
// Load the document to scan
PdfDocument pdf = PdfDocument.FromFile("suspicious-document.pdf");
// Scan using default YARA rules
CleanerScanResult scanResult = Cleaner.ScanPdf(pdf);
// Check the scan results
bool threatsDetected = scanResult.IsDetected;
int riskCount = scanResult.Risks.Count;
// Process identified risks
if (scanResult.IsDetected)
{
foreach (var risk in scanResult.Risks)
{
// Handle each identified risk
}
// Sanitize the document before use
PdfDocument sanitized = Cleaner.SanitizeWithSvg(pdf);
sanitized.SaveAs("suspicious-document-safe.pdf");
}
ImportsIronPdf' Load the document to scanDim pdf AsPdfDocument = PdfDocument.FromFile("suspicious-document.pdf")' Scan using default YARA rulesDim scanResult AsCleanerScanResult = Cleaner.ScanPdf(pdf)' Check the scan resultsDim threatsDetected AsBoolean = scanResult.IsDetectedDim riskCount AsInteger = scanResult.Risks.Count' Process identified risksIf scanResult.IsDetectedThen For Each risk In scanResult.Risks ' Handle each identified risk Next ' Sanitize the document before use Dim sanitized AsPdfDocument = Cleaner.SanitizeWithSvg(pdf) sanitized.SaveAs("suspicious-document-safe.pdf")End If
Imports IronPdf
' Load the document to scan
Dim pdf As PdfDocument = PdfDocument.FromFile("suspicious-document.pdf")
' Scan using default YARA rules
Dim scanResult As CleanerScanResult = Cleaner.ScanPdf(pdf)
' Check the scan results
Dim threatsDetected As Boolean = scanResult.IsDetected
Dim riskCount As Integer = scanResult.Risks.Count
' Process identified risks
If scanResult.IsDetected Then
For Each risk In scanResult.Risks
' Handle each identified risk
Next
' Sanitize the document before use
Dim sanitized As PdfDocument = Cleaner.SanitizeWithSvg(pdf)
sanitized.SaveAs("suspicious-document-safe.pdf")
End If
Można dostarczyć niestandardowe pliki reguł YARA w celu spełnienia specjalistycznych wymagań dotyczących wykrywania. Organizacje o specyficznych modelach zagrożeń lub wymaganiach dotyczących zgodności często utrzymują własne zestawy reguł ukierunkowane na konkretne wzorce podatności.
using IronPdf;PdfDocument pdf = PdfDocument.FromFile("incoming-document.pdf");// Scan with custom YARA rulesstring[] customYaraFiles = { "corporate-rules.yar", "industry-specific.yar" };CleanerScanResult result = Cleaner.ScanPdf(pdf, customYaraFiles);if (result.IsDetected){ // Document triggered custom rules and requires review or sanitization PdfDocument sanitized = Cleaner.SanitizeWithSvg(pdf); sanitized.SaveAs("incoming-document-safe.pdf");}
using IronPdf;
PdfDocument pdf = PdfDocument.FromFile("incoming-document.pdf");
// Scan with custom YARA rules
string[] customYaraFiles = { "corporate-rules.yar", "industry-specific.yar" };
CleanerScanResult result = Cleaner.ScanPdf(pdf, customYaraFiles);
if (result.IsDetected)
{
// Document triggered custom rules and requires review or sanitization
PdfDocument sanitized = Cleaner.SanitizeWithSvg(pdf);
sanitized.SaveAs("incoming-document-safe.pdf");
}
ImportsIronPdfDim pdf AsPdfDocument = PdfDocument.FromFile("incoming-document.pdf")' Scan with custom YARA rulesDim customYaraFiles AsString() = {"corporate-rules.yar", "industry-specific.yar"}Dim result AsCleanerScanResult = Cleaner.ScanPdf(pdf, customYaraFiles)If result.IsDetectedThen ' Document triggered custom rules and requires review or sanitization Dim sanitized AsPdfDocument = Cleaner.SanitizeWithSvg(pdf) sanitized.SaveAs("incoming-document-safe.pdf")End If
Imports IronPdf
Dim pdf As PdfDocument = PdfDocument.FromFile("incoming-document.pdf")
' Scan with custom YARA rules
Dim customYaraFiles As String() = {"corporate-rules.yar", "industry-specific.yar"}
Dim result As CleanerScanResult = Cleaner.ScanPdf(pdf, customYaraFiles)
If result.IsDetected Then
' Document triggered custom rules and requires review or sanitization
Dim sanitized As PdfDocument = Cleaner.SanitizeWithSvg(pdf)
sanitized.SaveAs("incoming-document-safe.pdf")
End If
Włączenie skanowania do procesów przyjmowania dokumentów pomaga zautomatyzować decyzje dotyczące bezpieczeństwa:
using IronPdf;using System;using System.IO;public enum DocumentSafetyLevel{Safe,Suspicious,Dangerous}public class DocumentSecurityGateway{ public DocumentSafetyLevelEvaluateDocument(string filePath) { PdfDocument pdf = PdfDocument.FromFile(filePath); CleanerScanResult scan = Cleaner.ScanPdf(pdf); if (!scan.IsDetected) { returnDocumentSafetyLevel.Safe; } // Evaluate severity based on number of risks if (scan.Risks.Count > 5) { returnDocumentSafetyLevel.Dangerous; } returnDocumentSafetyLevel.Suspicious; } public PdfDocumentProcessIncomingDocument(string filePath, string outputDirectory) { DocumentSafetyLevel safety = EvaluateDocument(filePath); string fileName = Path.GetFileName(filePath); switch (safety) { case DocumentSafetyLevel.Safe: returnPdfDocument.FromFile(filePath); case DocumentSafetyLevel.Suspicious: PdfDocument suspicious = PdfDocument.FromFile(filePath); returnCleaner.SanitizeWithSvg(suspicious); case DocumentSafetyLevel.Dangerous: throw new SecurityException($"Document {fileName} contains dangerous content"); default: throw new InvalidOperationException("Unknown safety level"); } }}
using IronPdf;
using System;
using System.IO;
public enum DocumentSafetyLevel
{
Safe,
Suspicious,
Dangerous
}
public class DocumentSecurityGateway
{
public DocumentSafetyLevel EvaluateDocument(string filePath)
{
PdfDocument pdf = PdfDocument.FromFile(filePath);
CleanerScanResult scan = Cleaner.ScanPdf(pdf);
if (!scan.IsDetected)
{
return DocumentSafetyLevel.Safe;
}
// Evaluate severity based on number of risks
if (scan.Risks.Count > 5)
{
return DocumentSafetyLevel.Dangerous;
}
return DocumentSafetyLevel.Suspicious;
}
public PdfDocument ProcessIncomingDocument(string filePath, string outputDirectory)
{
DocumentSafetyLevel safety = EvaluateDocument(filePath);
string fileName = Path.GetFileName(filePath);
switch (safety)
{
case DocumentSafetyLevel.Safe:
return PdfDocument.FromFile(filePath);
case DocumentSafetyLevel.Suspicious:
PdfDocument suspicious = PdfDocument.FromFile(filePath);
return Cleaner.SanitizeWithSvg(suspicious);
case DocumentSafetyLevel.Dangerous:
throw new SecurityException($"Document {fileName} contains dangerous content");
default:
throw new InvalidOperationException("Unknown safety level");
}
}
}
ImportsIronPdfImportsSystemImportsSystem.IOPublicEnumDocumentSafetyLevelSafeSuspiciousDangerousEndEnumPublic Class DocumentSecurityGateway Public Function EvaluateDocument(filePath AsString) AsDocumentSafetyLevel Dim pdf AsPdfDocument = PdfDocument.FromFile(filePath) Dim scan AsCleanerScanResult = Cleaner.ScanPdf(pdf) IfNot scan.IsDetectedThen ReturnDocumentSafetyLevel.Safe End If ' Evaluate severity based on number of risks If scan.Risks.Count > 5 Then ReturnDocumentSafetyLevel.Dangerous End If ReturnDocumentSafetyLevel.Suspicious End Function Public Function ProcessIncomingDocument(filePath AsString, outputDirectory AsString) AsPdfDocument Dim safety AsDocumentSafetyLevel = EvaluateDocument(filePath) Dim fileName AsString = Path.GetFileName(filePath) Select Case safety CaseDocumentSafetyLevel.Safe ReturnPdfDocument.FromFile(filePath) CaseDocumentSafetyLevel.Suspicious Dim suspicious AsPdfDocument = PdfDocument.FromFile(filePath) ReturnCleaner.SanitizeWithSvg(suspicious) CaseDocumentSafetyLevel.DangerousThrow New SecurityException($"Document {fileName} contains dangerous content") Case ElseThrow New InvalidOperationException("Unknown safety level") End Select End FunctionEnd Class
Imports IronPdf
Imports System
Imports System.IO
Public Enum DocumentSafetyLevel
Safe
Suspicious
Dangerous
End Enum
Public Class DocumentSecurityGateway
Public Function EvaluateDocument(filePath As String) As DocumentSafetyLevel
Dim pdf As PdfDocument = PdfDocument.FromFile(filePath)
Dim scan As CleanerScanResult = Cleaner.ScanPdf(pdf)
If Not scan.IsDetected Then
Return DocumentSafetyLevel.Safe
End If
' Evaluate severity based on number of risks
If scan.Risks.Count > 5 Then
Return DocumentSafetyLevel.Dangerous
End If
Return DocumentSafetyLevel.Suspicious
End Function
Public Function ProcessIncomingDocument(filePath As String, outputDirectory As String) As PdfDocument
Dim safety As DocumentSafetyLevel = EvaluateDocument(filePath)
Dim fileName As String = Path.GetFileName(filePath)
Select Case safety
Case DocumentSafetyLevel.Safe
Return PdfDocument.FromFile(filePath)
Case DocumentSafetyLevel.Suspicious
Dim suspicious As PdfDocument = PdfDocument.FromFile(filePath)
Return Cleaner.SanitizeWithSvg(suspicious)
Case DocumentSafetyLevel.Dangerous
Throw New SecurityException($"Document {fileName} contains dangerous content")
Case Else
Throw New InvalidOperationException("Unknown safety level")
End Select
End Function
End Class
Jak zbudować kompletny proces redagowania i czyszczenia danych?
Przetwarzanie dokumentów produkcyjnych zazwyczaj wymaga połączenia wielu technik zabezpieczeń w spójny proces. Kompletny proces może obejmować skanowanie przychodzących dokumentów pod kątem zagrożeń, oczyszczanie tych, które przeszły wstępną kontrolę, cenzurowanie tekstu i określonych obszarów, usuwanie metadanych oraz tworzenie dzienników audytowych dokumentujących wszystkie podjęte działania. Ten przykład ilustruje takie zintegrowane podejście.
using IronPdf;using IronSoftware.Drawing;using System;using System.Collections.Generic;using System.IO;using System.Text.RegularExpressions;public class DocumentProcessingResult{ public stringOriginalFile { get; set; } public stringOutputFile { get; set; } public boolWasSanitized { get; set; } public intTextRedactionsApplied { get; set; } public intRegionRedactionsApplied { get; set; } public boolMetadataCleaned { get; set; } public List<string> SensitiveDataTypesFound { get; set; } = new List<string>(); public DateTimeProcessedAt { get; set; } public boolSuccess { get; set; } public stringErrorMessage { get; set; }}public class ComprehensiveDocumentProcessor{ // Sensitive data patterns private readonly Dictionary<string, string> _sensitivePatterns = new Dictionary<string, string> { { "SSN", @"\b\d{3}-\d{2}-\d{4}\b" }, { "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" }, { "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" }, { "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" } }; // Standard regions to redact (signature areas, photo locations) private readonly List<RectangleF> _standardRedactionRegions = new List<RectangleF> { new RectangleF(72, 72, 200, 50), // Bottom left signature new RectangleF(350, 72, 200, 50) // Bottom right signature }; private readonly string _organizationName; publicComprehensiveDocumentProcessor(string organizationName) { _organizationName = organizationName; } public DocumentProcessingResultProcessDocument( string inputPath, string outputPath, bool sanitize = true, bool redactPatterns = true, bool redactRegions = true, bool cleanMetadata = true, List<string> additionalTermsToRedact = null) { var result = new DocumentProcessingResult {OriginalFile = inputPath,OutputFile = outputPath,ProcessedAt = DateTime.Now }; try { // Load the document PdfDocument pdf = PdfDocument.FromFile(inputPath); // Step 1: Security scan CleanerScanResult scanResult = Cleaner.ScanPdf(pdf); if (scanResult.IsDetected && scanResult.Risks.Count > 10) { throw new SecurityException("Document contains too many security risks to process"); } // Step 2: Sanitization (if needed or requested) if (sanitize || scanResult.IsDetected) { pdf = Cleaner.SanitizeWithSvg(pdf); result.WasSanitized = true; } // Step 3: Pattern-based text redaction if (redactPatterns) { string fullText = pdf.ExtractAllText(); HashSet<string> valuesToRedact = new HashSet<string>(); foreach (var pattern in _sensitivePatterns) { Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase); MatchCollection matches = regex.Matches(fullText); if (matches.Count > 0) { result.SensitiveDataTypesFound.Add($"{pattern.Key} ({matches.Count})"); foreach (Match match in matches) { valuesToRedact.Add(match.Value); } } } // Apply redactions foreach (string value in valuesToRedact) { pdf.RedactTextOnAllPages(value); result.TextRedactionsApplied++; } } // Step 4: Additional specific terms if (additionalTermsToRedact != null) { foreach (string term in additionalTermsToRedact) { pdf.RedactTextOnAllPages(term); result.TextRedactionsApplied++; } } // Step 5: Region-based redaction if (redactRegions) { foreach (RectangleF region in _standardRedactionRegions) { pdf.RedactRegionsOnAllPages(region); result.RegionRedactionsApplied++; } } // Step 6: Metadata cleaning if (cleanMetadata) { pdf.MetaData.Author = _organizationName; pdf.MetaData.Creator = $"{_organizationName} Document Processor"; pdf.MetaData.Producer = ""; pdf.MetaData.Subject = ""; pdf.MetaData.Keywords = ""; pdf.MetaData.CreationDate = DateTime.Now; pdf.MetaData.ModifiedDate = DateTime.Now; result.MetadataCleaned = true; } // Step 7: Save the processed document pdf.SaveAs(outputPath); result.Success = true; } catch (Exception ex) { result.Success = false; result.ErrorMessage = ex.Message; } return result; }}// Usage exampleclass Program{ static voidMain() { var processor = new ComprehensiveDocumentProcessor("Acme Corporation"); // Process a single document with all protections var result = processor.ProcessDocument( inputPath: "customer-application.pdf", outputPath: "customer-application-redacted.pdf", sanitize: true, redactPatterns: true, redactRegions: true, cleanMetadata: true, additionalTermsToRedact: new List<string> { "Project Alpha", "Internal Use Only" } ); // Batch process multiple documents string[] inputFiles = Directory.GetFiles("incoming", "*.pdf"); foreach (string file in inputFiles) { string outputFile = Path.Combine("processed", Path.GetFileName(file)); processor.ProcessDocument(file, outputFile); } }}
using IronPdf;
using IronSoftware.Drawing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
public class DocumentProcessingResult
{
public string OriginalFile { get; set; }
public string OutputFile { get; set; }
public bool WasSanitized { get; set; }
public int TextRedactionsApplied { get; set; }
public int RegionRedactionsApplied { get; set; }
public bool MetadataCleaned { get; set; }
public List<string> SensitiveDataTypesFound { get; set; } = new List<string>();
public DateTime ProcessedAt { get; set; }
public bool Success { get; set; }
public string ErrorMessage { get; set; }
}
public class ComprehensiveDocumentProcessor
{
// Sensitive data patterns
private readonly Dictionary<string, string> _sensitivePatterns = new Dictionary<string, string>
{
{ "SSN", @"\b\d{3}-\d{2}-\d{4}\b" },
{ "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
{ "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
{ "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" }
};
// Standard regions to redact (signature areas, photo locations)
private readonly List<RectangleF> _standardRedactionRegions = new List<RectangleF>
{
new RectangleF(72, 72, 200, 50), // Bottom left signature
new RectangleF(350, 72, 200, 50) // Bottom right signature
};
private readonly string _organizationName;
public ComprehensiveDocumentProcessor(string organizationName)
{
_organizationName = organizationName;
}
public DocumentProcessingResult ProcessDocument(
string inputPath,
string outputPath,
bool sanitize = true,
bool redactPatterns = true,
bool redactRegions = true,
bool cleanMetadata = true,
List<string> additionalTermsToRedact = null)
{
var result = new DocumentProcessingResult
{
OriginalFile = inputPath,
OutputFile = outputPath,
ProcessedAt = DateTime.Now
};
try
{
// Load the document
PdfDocument pdf = PdfDocument.FromFile(inputPath);
// Step 1: Security scan
CleanerScanResult scanResult = Cleaner.ScanPdf(pdf);
if (scanResult.IsDetected && scanResult.Risks.Count > 10)
{
throw new SecurityException("Document contains too many security risks to process");
}
// Step 2: Sanitization (if needed or requested)
if (sanitize || scanResult.IsDetected)
{
pdf = Cleaner.SanitizeWithSvg(pdf);
result.WasSanitized = true;
}
// Step 3: Pattern-based text redaction
if (redactPatterns)
{
string fullText = pdf.ExtractAllText();
HashSet<string> valuesToRedact = new HashSet<string>();
foreach (var pattern in _sensitivePatterns)
{
Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(fullText);
if (matches.Count > 0)
{
result.SensitiveDataTypesFound.Add($"{pattern.Key} ({matches.Count})");
foreach (Match match in matches)
{
valuesToRedact.Add(match.Value);
}
}
}
// Apply redactions
foreach (string value in valuesToRedact)
{
pdf.RedactTextOnAllPages(value);
result.TextRedactionsApplied++;
}
}
// Step 4: Additional specific terms
if (additionalTermsToRedact != null)
{
foreach (string term in additionalTermsToRedact)
{
pdf.RedactTextOnAllPages(term);
result.TextRedactionsApplied++;
}
}
// Step 5: Region-based redaction
if (redactRegions)
{
foreach (RectangleF region in _standardRedactionRegions)
{
pdf.RedactRegionsOnAllPages(region);
result.RegionRedactionsApplied++;
}
}
// Step 6: Metadata cleaning
if (cleanMetadata)
{
pdf.MetaData.Author = _organizationName;
pdf.MetaData.Creator = $"{_organizationName} Document Processor";
pdf.MetaData.Producer = "";
pdf.MetaData.Subject = "";
pdf.MetaData.Keywords = "";
pdf.MetaData.CreationDate = DateTime.Now;
pdf.MetaData.ModifiedDate = DateTime.Now;
result.MetadataCleaned = true;
}
// Step 7: Save the processed document
pdf.SaveAs(outputPath);
result.Success = true;
}
catch (Exception ex)
{
result.Success = false;
result.ErrorMessage = ex.Message;
}
return result;
}
}
// Usage example
class Program
{
static void Main()
{
var processor = new ComprehensiveDocumentProcessor("Acme Corporation");
// Process a single document with all protections
var result = processor.ProcessDocument(
inputPath: "customer-application.pdf",
outputPath: "customer-application-redacted.pdf",
sanitize: true,
redactPatterns: true,
redactRegions: true,
cleanMetadata: true,
additionalTermsToRedact: new List<string> { "Project Alpha", "Internal Use Only" }
);
// Batch process multiple documents
string[] inputFiles = Directory.GetFiles("incoming", "*.pdf");
foreach (string file in inputFiles)
{
string outputFile = Path.Combine("processed", Path.GetFileName(file));
processor.ProcessDocument(file, outputFile);
}
}
}
ImportsIronPdfImportsIronSoftware.DrawingImportsSystemImportsSystem.Collections.GenericImportsSystem.IOImportsSystem.Text.RegularExpressionsPublic Class DocumentProcessingResult Public Property OriginalFileAsString Public Property OutputFileAsString Public Property WasSanitizedAsBoolean Public Property TextRedactionsAppliedAsInteger Public Property RegionRedactionsAppliedAsInteger Public Property MetadataCleanedAsBoolean Public Property SensitiveDataTypesFoundAsList(OfString) = New List(OfString)() Public Property ProcessedAtAsDateTime Public Property SuccessAsBoolean Public Property ErrorMessageAsStringEnd ClassPublic Class ComprehensiveDocumentProcessor ' Sensitive data patterns PrivateReadOnly _sensitivePatterns AsDictionary(OfString, String) = New Dictionary(OfString, String) From { {"SSN", "\b\d{3}-\d{2}-\d{4}\b"}, {"Credit Card", "\b(?:\d{4}[-\s]?){3}\d{1,4}\b"}, {"Email", "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"}, {"Phone", "\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b"} } ' Standard regions to redact (signature areas, photo locations) PrivateReadOnly _standardRedactionRegions AsList(OfRectangleF) = New List(OfRectangleF) From { New RectangleF(72, 72, 200, 50), ' Bottom left signature New RectangleF(350, 72, 200, 50) ' Bottom right signature } PrivateReadOnly _organizationName AsString Public Sub New(organizationName AsString) _organizationName = organizationName End Sub Public Function ProcessDocument( inputPath AsString, outputPath AsString,Optional sanitize AsBoolean = True,Optional redactPatterns AsBoolean = True,Optional redactRegions AsBoolean = True,Optional cleanMetadata AsBoolean = True,Optional additionalTermsToRedact AsList(OfString) = Nothing) AsDocumentProcessingResult Dim result As New DocumentProcessingResultWith { .OriginalFile = inputPath, .OutputFile = outputPath, .ProcessedAt = DateTime.Now }Try ' Load the document Dim pdf AsPdfDocument = PdfDocument.FromFile(inputPath) ' Step 1: Security scan Dim scanResult AsCleanerScanResult = Cleaner.ScanPdf(pdf) If scanResult.IsDetectedAndAlso scanResult.Risks.Count > 10 ThenThrow New SecurityException("Document contains too many security risks to process") End If ' Step 2: Sanitization (if needed or requested) If sanitize OrElse scanResult.IsDetectedThen pdf = Cleaner.SanitizeWithSvg(pdf) result.WasSanitized = True End If ' Step 3: Pattern-based text redaction If redactPatterns Then Dim fullText AsString = pdf.ExtractAllText() Dim valuesToRedact As New HashSet(OfString)() For Each pattern In _sensitivePatterns Dim regex As New Regex(pattern.Value, RegexOptions.IgnoreCase) Dim matches AsMatchCollection = regex.Matches(fullText) If matches.Count > 0 Then result.SensitiveDataTypesFound.Add($"{pattern.Key} ({matches.Count})") For Each match AsMatchIn matches valuesToRedact.Add(match.Value) Next End If Next ' Apply redactions For Each value AsStringIn valuesToRedact pdf.RedactTextOnAllPages(value) result.TextRedactionsApplied += 1 Next End If ' Step 4: Additional specific terms If additionalTermsToRedact IsNot Nothing Then For Each term AsStringIn additionalTermsToRedact pdf.RedactTextOnAllPages(term) result.TextRedactionsApplied += 1 Next End If ' Step 5: Region-based redaction If redactRegions Then For Each region AsRectangleFIn _standardRedactionRegions pdf.RedactRegionsOnAllPages(region) result.RegionRedactionsApplied += 1 Next End If ' Step 6: Metadata cleaning If cleanMetadata Then pdf.MetaData.Author = _organizationName pdf.MetaData.Creator = $"{_organizationName} Document Processor" pdf.MetaData.Producer = "" pdf.MetaData.Subject = "" pdf.MetaData.Keywords = "" pdf.MetaData.CreationDate = DateTime.Now pdf.MetaData.ModifiedDate = DateTime.Now result.MetadataCleaned = True End If ' Step 7: Save the processed document pdf.SaveAs(outputPath) result.Success = TrueCatch ex AsException result.Success = False result.ErrorMessage = ex.MessageEndTry Return result End FunctionEnd Class' Usage exampleClass ProgramShared Sub Main() Dim processor As New ComprehensiveDocumentProcessor("Acme Corporation") ' Process a single document with all protections Dim result = processor.ProcessDocument( inputPath:="customer-application.pdf", outputPath:="customer-application-redacted.pdf", sanitize:=True, redactPatterns:=True, redactRegions:=True, cleanMetadata:=True, additionalTermsToRedact:=New List(OfString) From {"Project Alpha", "Internal Use Only"} ) ' Batch process multiple documents Dim inputFiles AsString() = Directory.GetFiles("incoming", "*.pdf") For Each file AsStringIn inputFiles Dim outputFile AsString = Path.Combine("processed", Path.GetFileName(file)) processor.ProcessDocument(file, outputFile) Next End SubEnd Class
Imports IronPdf
Imports IronSoftware.Drawing
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Text.RegularExpressions
Public Class DocumentProcessingResult
Public Property OriginalFile As String
Public Property OutputFile As String
Public Property WasSanitized As Boolean
Public Property TextRedactionsApplied As Integer
Public Property RegionRedactionsApplied As Integer
Public Property MetadataCleaned As Boolean
Public Property SensitiveDataTypesFound As List(Of String) = New List(Of String)()
Public Property ProcessedAt As DateTime
Public Property Success As Boolean
Public Property ErrorMessage As String
End Class
Public Class ComprehensiveDocumentProcessor
' Sensitive data patterns
Private ReadOnly _sensitivePatterns As Dictionary(Of String, String) = New Dictionary(Of String, String) From {
{"SSN", "\b\d{3}-\d{2}-\d{4}\b"},
{"Credit Card", "\b(?:\d{4}[-\s]?){3}\d{1,4}\b"},
{"Email", "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"},
{"Phone", "\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b"}
}
' Standard regions to redact (signature areas, photo locations)
Private ReadOnly _standardRedactionRegions As List(Of RectangleF) = New List(Of RectangleF) From {
New RectangleF(72, 72, 200, 50), ' Bottom left signature
New RectangleF(350, 72, 200, 50) ' Bottom right signature
}
Private ReadOnly _organizationName As String
Public Sub New(organizationName As String)
_organizationName = organizationName
End Sub
Public Function ProcessDocument(
inputPath As String,
outputPath As String,
Optional sanitize As Boolean = True,
Optional redactPatterns As Boolean = True,
Optional redactRegions As Boolean = True,
Optional cleanMetadata As Boolean = True,
Optional additionalTermsToRedact As List(Of String) = Nothing) As DocumentProcessingResult
Dim result As New DocumentProcessingResult With {
.OriginalFile = inputPath,
.OutputFile = outputPath,
.ProcessedAt = DateTime.Now
}
Try
' Load the document
Dim pdf As PdfDocument = PdfDocument.FromFile(inputPath)
' Step 1: Security scan
Dim scanResult As CleanerScanResult = Cleaner.ScanPdf(pdf)
If scanResult.IsDetected AndAlso scanResult.Risks.Count > 10 Then
Throw New SecurityException("Document contains too many security risks to process")
End If
' Step 2: Sanitization (if needed or requested)
If sanitize OrElse scanResult.IsDetected Then
pdf = Cleaner.SanitizeWithSvg(pdf)
result.WasSanitized = True
End If
' Step 3: Pattern-based text redaction
If redactPatterns Then
Dim fullText As String = pdf.ExtractAllText()
Dim valuesToRedact As New HashSet(Of String)()
For Each pattern In _sensitivePatterns
Dim regex As New Regex(pattern.Value, RegexOptions.IgnoreCase)
Dim matches As MatchCollection = regex.Matches(fullText)
If matches.Count > 0 Then
result.SensitiveDataTypesFound.Add($"{pattern.Key} ({matches.Count})")
For Each match As Match In matches
valuesToRedact.Add(match.Value)
Next
End If
Next
' Apply redactions
For Each value As String In valuesToRedact
pdf.RedactTextOnAllPages(value)
result.TextRedactionsApplied += 1
Next
End If
' Step 4: Additional specific terms
If additionalTermsToRedact IsNot Nothing Then
For Each term As String In additionalTermsToRedact
pdf.RedactTextOnAllPages(term)
result.TextRedactionsApplied += 1
Next
End If
' Step 5: Region-based redaction
If redactRegions Then
For Each region As RectangleF In _standardRedactionRegions
pdf.RedactRegionsOnAllPages(region)
result.RegionRedactionsApplied += 1
Next
End If
' Step 6: Metadata cleaning
If cleanMetadata Then
pdf.MetaData.Author = _organizationName
pdf.MetaData.Creator = $"{_organizationName} Document Processor"
pdf.MetaData.Producer = ""
pdf.MetaData.Subject = ""
pdf.MetaData.Keywords = ""
pdf.MetaData.CreationDate = DateTime.Now
pdf.MetaData.ModifiedDate = DateTime.Now
result.MetadataCleaned = True
End If
' Step 7: Save the processed document
pdf.SaveAs(outputPath)
result.Success = True
Catch ex As Exception
result.Success = False
result.ErrorMessage = ex.Message
End Try
Return result
End Function
End Class
' Usage example
Class Program
Shared Sub Main()
Dim processor As New ComprehensiveDocumentProcessor("Acme Corporation")
' Process a single document with all protections
Dim result = processor.ProcessDocument(
inputPath:="customer-application.pdf",
outputPath:="customer-application-redacted.pdf",
sanitize:=True,
redactPatterns:=True,
redactRegions:=True,
cleanMetadata:=True,
additionalTermsToRedact:=New List(Of String) From {"Project Alpha", "Internal Use Only"}
)
' Batch process multiple documents
Dim inputFiles As String() = Directory.GetFiles("incoming", "*.pdf")
For Each file As String In inputFiles
Dim outputFile As String = Path.Combine("processed", Path.GetFileName(file))
processor.ProcessDocument(file, outputFile)
Next
End Sub
End Class
Wejscie
Formularz zgłoszeniowy klienta zawierający wiele rodzajów danych wrażliwych, w tym numery ubezpieczenia społecznego, numery kart kredytowych, adresy e-mail i bloki podpisów, wymagające kompleksowej ochrony.
Przykładowy Wynik
Ten wszechstronny procesor łączy wszystkie techniki omówione w tym przewodniku w jedną, konfigurowalną klasę. Wyszukuje zagrożenia, w razie potrzeby oczyszcza dane, wyszukuje i redaguje wrażliwe wzorce, stosuje redagowanie regionów, czyści metadane i generuje szczegółowe raporty. Możesz dostosować wzorce wrażliwości, obszary redagowania i opcje przetwarzania, aby dopasować je do swoich konkretnych wymagań.
Kolejne kroki
Ochrona poufnych informacji w dokumentach PDF wymaga czegoś więcej niż tylko powierzchownych środków. Prawdziwa redakcja trwałe usuwa treść ze struktury dokumentu. Dopasowywanie wzorców automatyzuje wykrywanie i usuwanie danych, takich jak numery ubezpieczenia społecznego, dane kart kredytowych i adresy e-mail. Redakcja oparta na regionach zajmuje się podpisami, zdjęciami i innymi elementami graficznymi, których nie można uwzględnić w dopasowaniu tekstu. Czyszczenie metadanych eliminuje ukryte informacje, które mogłyby ujawnić autorów, znaczniki czasu lub wewnętrzne ścieżki plików. Oczyszczanie usuwa osadzone skrypty i aktywną zawartość, które stanowią zagrożenie dla bezpieczeństwa.
IronPDF zapewnia wszystkie te możliwości poprzez spójny, dobrze zaprojektowany interfejs API, który w naturalny sposób integruje się z praktykami programistycznymi w języku C# i platformie .NET. Metody przedstawione w tym przewodniku obsługują pojedyncze dokumenty lub skalują się do przetwarzania wsadowego tysięcy plików. Niezależnie od tego, czy tworzysz procesy zapewnienia zgodności dla danych medycznych, przygotowujesz dokumenty prawne do ujawnienia, czy po prostu dbasz o to, by raporty wewnętrzne mogły być bezpiecznie udostępniane na zewnątrz, techniki te stanowią podstawę odpowiedzialnego postępowania z dokumentami. Aby zapewnić kompleksową ochronę bezpieczeństwa, należy połączyć redagowanie z ochroną hasłem, uprawnieniami i podpisami cyfrowymi.
Czy jesteś gotowy do rozpoczęcia budowy? Pobierz IronPDF i wyprobuj go z darmowa wersja probna. Biblioteka zawiera bezpłatną licencję deweloperską, dzięki czemu można w pełni ocenić możliwości redagowania, ekstrakcji tekstu i czyszczenia danych przed zakupem licencji produkcyjnej. Jeśli masz pytania dotyczące wdrażania lub procesów zapewnienia zgodności, skontaktuj się z naszym zespołem wsparcia technicznego.
Często Zadawane Pytania
Co to jest redakcja PDF?
Redakcja PDF to proces trwalego usuwania wrazliwych informacji z dokumentu PDF. Moze to obejmowac tekst, obrazy i metadane, ktore należy ukryć z uwagi na prywatność lub wymagania zgodności.
Jak moge redagowac informacje w PDF uzywajac C#?
Mozesz uzywac IronPDF do redagowania informacji w PDF uzywajac C#. Pozwala to na trwale usuwanie lub ukrywanie tekstu, obrazow i metadanych w dokumentach PDF, zapewniając ich zgodność ze standardami prywatności i ochrony danych.
Dlaczego redakcja PDF jest wazna dla zgodnosci?
Redakcja PDF jest kluczowa dla zgodnosci ze standardami takimi jak HIPAA, GDPR i PCI DSS, poniewaz pomaga w zabezpieczaniu wrazliwych danych i zapobieganiu nieautoryzowanemu dostepu do poufnych informacji.
Czy IronPDF moze redagowac cale regiony PDF?
Tak, IronPDF moze redagowac cale regiony PDF. Pozwala to zdefiniowac okreslone obszary w dokumencie, ktore nalezy ukryc lub usunac w celach bezpieczenstwa.
Jakie typy danych moga zostac zredagowane za pomoca IronPDF?
IronPDF moze redagowac rozne typy danych, w tym tekst, obrazy i metadane z dokumentow PDF, zapewniając kompleksową prywatność i bezpieczeństwo danych.
Czy IronPDF wspiera oczyszczanie dokumentow?
Tak, IronPDF wspiera oczyszczanie dokumentow, co polega na czyszczeniu PDFow w celu usuniecia ukrytych danych lub metadanych, które moga nie byc widoczne, ale mogą stwarzać ryzyko dla prywatności.
Czy mozna zautomatyzowac proces redakcji PDF za pomoca IronPDF?
Tak, IronPDF pozwala na automatyzację procesow redakcji PDF w C#, co ulatwia obsluge dużej ilosci dokumentów wymagających usunięcia wrazliwych danych.
Jak IronPDF zapewnia trwałość redakcji?
IronPDF zapewnia trwałość redakcji poprzez trwale usuwanie wybranego tekstu i obrazów z dokumentu, zamiast jedynie ich ukrywania, co oznacza, ze nie moga one byc odzyskane lub widoczne.
Czy IronPDF moze redagowac metadane w PDF?
Tak, IronPDF moze redagowac metadane w dokumencie PDF, zapewniając, ze wszystkie formy wrazliwych danych, w tym dane ukryte lub w tle, są dokładnie usunięte.
Jakie są korzyści z używania IronPDF do redakcji PDF?
Uzycie IronPDF do redakcji PDF oferuje korzyści takie jak zapewnienie zgodności z regulacjami dotyczącymi ochrony danych, zwiększenie bezpieczeństwa dokumentow oraz zapewnienie efektywnego, zautomatyzowanego procesu zarządzania danymi wrażliwymi.
Curtis Chau posiada tytuł licencjata z informatyki (Uniwersytet Carleton) i specjalizuje się w front-endowym rozwoju, z ekspertką w Node.js, TypeScript, JavaScript i React. Pasjonuje się tworzeniem intuicyjnych i estetycznie przyjemnych interfejsów użytkownika, Curtis cieszy się pracą z nowoczesnymi frameworkami i tworzeniem dobrze zorganizowanych, atrakcyjnych wizualnie podręczników.