Konwertuj HTML do PDF za uwierzytelnieniem logowania w C
Aby przekonwertować HTML na PDF za uwierzytelnieniem logowania w C#, użyj ChromeHttpLoginCredentials IronPDF do uwierzytelnienia sieciowego lub pobierz HTML za pomocą HttpClient przed konwersją. To podejście skutecznie obsługuje zarówno uwierzytelnienie sieciowe, jak i logowania w formularzach HTML.
Quickstart: Konwertuj HTML na PDF za logowaniem z IronPDF
Konwertuj strony HTML do PDF za formularzami logowania używając API IronPDF. Ten przewodnik demonstruje ChromeHttpLoginCredentials do uwierzytelnienia i pobierania chronionej zawartości. Obsługuj zarówno uwierzytelnienie sieciowe, jak i logowania w formularzach HTML z prostymi przykładami kodu.
-
Install IronPDF with NuGet Package Manager
PM > Install-Package IronPdf -
Skopiuj i uruchom ten fragment kodu.
new ChromePdfRenderer { LoginCredentials = new ChromeHttpLoginCredentials("username","password") } .RenderUrlAsPdf("https://example.com/protected") .SaveAs("secure.pdf"); -
Wdrożenie do testowania w środowisku produkcyjnym
Rozpocznij używanie IronPDF w swoim projekcie już dziś z darmową wersją próbną
Minimalny proces (5 kroków)
- Pobierz bibliotekę C# IronPDF
- Pobierz HTML, aby uniknąć logowania
- Zaloguj się, używając uwierzytelnienia sieciowego z właściwością
LoginCredentials - Użyj formularza HTML do uwierzytelnienia
- Obejście dla uwierzytelniania logowania MVC
Jakie są najlepsze praktyki obsługi uwierzytelniania logowania?
IronPDF wspiera sieciowe uwierzytelnienie TLS (nazwa użytkownika i hasło) poprzez ChromeHttpLoginCredentials API. Dla kompleksowych wskazówek dotyczących różnych scenariuszy logowania, zobacz poradnik logowań TLS Website & System.
Zalecanym podejściem jest użycie System.Net.WebClient lub HttpClient do pobrania HTML i zasobów. Ta metoda wspiera nagłówki, logowania i inne wymagania. Po pobraniu do pamięci lub na dysk, IronPDF konwertuje HTML do PDF. Wyodrębnij zasoby takie jak style i obrazki za pomocą HtmlAgilityPack, a następnie pobierz z System.Net.WebClient.
// Download HTML content from a URL with authentication
string html;
using (WebClient client = new WebClient())
{
// Add authentication headers if needed
client.Headers.Add("Authorization", "Bearer " + accessToken);
// Download the HTML string
html = client.DownloadString("http://www.example.com/protected-content");
}
// Load the HTML into an HtmlDocument for parsing
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
// Extract all image sources for downloading
foreach(HtmlNode img in doc.DocumentNode.SelectNodes("//img"))
{
string imgSrc = img.GetAttributeValue("src", null);
Console.WriteLine($"Found image: {imgSrc}");
// Download each image asset
if (!string.IsNullOrEmpty(imgSrc))
{
string fileName = Path.GetFileName(imgSrc);
client.DownloadFile(imgSrc, fileName);
}
}
// Convert the downloaded HTML to PDF
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("authenticated-content.pdf");
// Download HTML content from a URL with authentication
string html;
using (WebClient client = new WebClient())
{
// Add authentication headers if needed
client.Headers.Add("Authorization", "Bearer " + accessToken);
// Download the HTML string
html = client.DownloadString("http://www.example.com/protected-content");
}
// Load the HTML into an HtmlDocument for parsing
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
// Extract all image sources for downloading
foreach(HtmlNode img in doc.DocumentNode.SelectNodes("//img"))
{
string imgSrc = img.GetAttributeValue("src", null);
Console.WriteLine($"Found image: {imgSrc}");
// Download each image asset
if (!string.IsNullOrEmpty(imgSrc))
{
string fileName = Path.GetFileName(imgSrc);
client.DownloadFile(imgSrc, fileName);
}
}
// Convert the downloaded HTML to PDF
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("authenticated-content.pdf");
Imports System.Net
Imports HtmlAgilityPack
Imports IronPdf
' Download HTML content from a URL with authentication
Dim html As String
Using client As New WebClient()
' Add authentication headers if needed
client.Headers.Add("Authorization", "Bearer " & accessToken)
' Download the HTML string
html = client.DownloadString("http://www.example.com/protected-content")
End Using
' Load the HTML into an HtmlDocument for parsing
Dim doc As New HtmlDocument()
doc.LoadHtml(html)
' Extract all image sources for downloading
For Each img As HtmlNode In doc.DocumentNode.SelectNodes("//img")
Dim imgSrc As String = img.GetAttributeValue("src", Nothing)
Console.WriteLine($"Found image: {imgSrc}")
' Download each image asset
If Not String.IsNullOrEmpty(imgSrc) Then
Dim fileName As String = Path.GetFileName(imgSrc)
Using client As New WebClient()
client.DownloadFile(imgSrc, fileName)
End Using
End If
Next
' Convert the downloaded HTML to PDF
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("authenticated-content.pdf")
System.Uri. Aby zmienić wszystkie ścieżki względne w dokumencie HTML, dodaj znacznik <base> do nagłówka używając HtmlAgilityPack. Przykład. Więcej informacji na temat obsługi URL-i i zasobów znajdziesz w przewodniku Base URLs & Asset Encoding.Dlaczego powinienem najpierw pobrać zawartość HTML?
Pobieranie zawartości HTML przed konwersją oferuje kilka korzyści:
- Pełna kontrola: Modyfikuj HTML, naprawiaj uszkodzone linki lub wstawiaj tokeny uwierzytelniające przed konwersją
- Zarządzanie zasobami: Pobieraj i zapisuj zewnętrzne zasoby, takie jak obrazy, CSS i pliki JavaScript
- Elastyczność uwierzytelnienia: Użyj dowolnego mechanizmu uwierzytelniania .NET, w tym OAuth, tokenów JWT, lub niestandardowych nagłówków
- Wydajność: Buforuj często dostępne treści w celu zmniejszenia obciążenia serwera
- Debugging: Sprawdź dokładny HTML przekształcany w celu rozwiązywania problemów
W przypadku złożonych scenariuszy uwierzytelniania obejmujących ciasteczka i sesje, zobacz przewodnik Cookies, który tłumaczy zarządzanie stanem uwierzytelnienia w trakcie konwersji PDF.
Jak obsługiwać zasoby takie jak obrazy i arkusze stylów?
Podczas konwersji uwierzytelnionych stron, zewnętrzne zasoby często wymagają tego samego uwierzytelnienia. Oto kompleksowe podejście z użyciem HttpClient:
public async Task<string> DownloadAuthenticatedHtmlWithAssets(string url, string authToken)
{
using (var client = new HttpClient())
{
// Set authentication header
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authToken);
// Download the main HTML
string html = await client.GetStringAsync(url);
// Parse HTML to find assets
var doc = new HtmlDocument();
doc.LoadHtml(html);
// Create a base URI for resolving relative paths
var baseUri = new Uri(url);
// Download CSS files
var cssLinks = doc.DocumentNode.SelectNodes("//link[@rel='stylesheet']");
if (cssLinks != null)
{
foreach (var link in cssLinks)
{
string href = link.GetAttributeValue("href", "");
if (!string.IsNullOrEmpty(href))
{
var cssUri = new Uri(baseUri, href);
string cssContent = await client.GetStringAsync(cssUri);
// Embed CSS directly in the HTML
var styleNode = doc.CreateElement("style");
styleNode.InnerHtml = cssContent;
doc.DocumentNode.SelectSingleNode("//head").AppendChild(styleNode);
// Remove the external link
link.Remove();
}
}
}
// Return the modified HTML with embedded assets
return doc.DocumentNode.OuterHtml;
}
}
public async Task<string> DownloadAuthenticatedHtmlWithAssets(string url, string authToken)
{
using (var client = new HttpClient())
{
// Set authentication header
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authToken);
// Download the main HTML
string html = await client.GetStringAsync(url);
// Parse HTML to find assets
var doc = new HtmlDocument();
doc.LoadHtml(html);
// Create a base URI for resolving relative paths
var baseUri = new Uri(url);
// Download CSS files
var cssLinks = doc.DocumentNode.SelectNodes("//link[@rel='stylesheet']");
if (cssLinks != null)
{
foreach (var link in cssLinks)
{
string href = link.GetAttributeValue("href", "");
if (!string.IsNullOrEmpty(href))
{
var cssUri = new Uri(baseUri, href);
string cssContent = await client.GetStringAsync(cssUri);
// Embed CSS directly in the HTML
var styleNode = doc.CreateElement("style");
styleNode.InnerHtml = cssContent;
doc.DocumentNode.SelectSingleNode("//head").AppendChild(styleNode);
// Remove the external link
link.Remove();
}
}
}
// Return the modified HTML with embedded assets
return doc.DocumentNode.OuterHtml;
}
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Imports HtmlAgilityPack
Public Class HtmlDownloader
Public Async Function DownloadAuthenticatedHtmlWithAssets(url As String, authToken As String) As Task(Of String)
Using client As New HttpClient()
' Set authentication header
client.DefaultRequestHeaders.Authorization = New System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authToken)
' Download the main HTML
Dim html As String = Await client.GetStringAsync(url)
' Parse HTML to find assets
Dim doc As New HtmlDocument()
doc.LoadHtml(html)
' Create a base URI for resolving relative paths
Dim baseUri As New Uri(url)
' Download CSS files
Dim cssLinks = doc.DocumentNode.SelectNodes("//link[@rel='stylesheet']")
If cssLinks IsNot Nothing Then
For Each link In cssLinks
Dim href As String = link.GetAttributeValue("href", "")
If Not String.IsNullOrEmpty(href) Then
Dim cssUri As New Uri(baseUri, href)
Dim cssContent As String = Await client.GetStringAsync(cssUri)
' Embed CSS directly in the HTML
Dim styleNode = doc.CreateElement("style")
styleNode.InnerHtml = cssContent
doc.DocumentNode.SelectSingleNode("//head").AppendChild(styleNode)
' Remove the external link
link.Remove()
End If
Next
End If
' Return the modified HTML with embedded assets
Return doc.DocumentNode.OuterHtml
End Using
End Function
End Class
Jakie narzędzia pomagają z parsowaniem HTML?
HtmlAgilityPack to najpopularniejsza biblioteka do parsowania HTML dla .NET, ale istnieją alternatywy:
- HtmlAgilityPack: Najlepsze do ogólnego parsowania i manipulacji HTML
- AngleSharp: Nowoczesny, zgodny ze standardami parser HTML z obsługą selektorów CSS
- CsQuery: Składnia podobna do jQuery dla deweloperów C# zaznajomionych z jQuery
- Regular Expressions: Do prostych zadań ekstrakcji (niezalecane do skomplikowanego HTML)
Jak zalogować się używając uwierzytelnienia sieciowego?
Większość aplikacji ASP.NET obsługuje uwierzytelnienie sieciowe, które jest bardziej niezawodne niż wysyłanie formularza HTML. IronPDF oferuje wbudowane wsparcie dla podstawowego, digest i NTLM uwierzytelnienia przez klasę ChromeHttpLoginCredentials. W celu dodatkowego dostosowania nagłówków zobacz przewodnik nagłówków żądań HTTP.
:path=/static-assets/pdf/content-code-examples/how-to/logins-username-password.cs
using IronPdf;
using System;
ChromePdfRenderer renderer = new ChromePdfRenderer
{
// setting login credentials to bypass basic authentication
LoginCredentials = new ChromeHttpLoginCredentials()
{
NetworkUsername = "testUser",
NetworkPassword = "testPassword"
}
};
var uri = new Uri("http://localhost:51169/Invoice");
// Render web URL to PDF
PdfDocument pdf = renderer.RenderUrlAsPdf(uri);
// Export PDF
pdf.SaveAs("UrlToPdfExample.Pdf");
Imports IronPdf
Imports System
Private renderer As New ChromePdfRenderer With {
.LoginCredentials = New ChromeHttpLoginCredentials() With {
.NetworkUsername = "testUser",
.NetworkPassword = "testPassword"
}
}
Private uri = New Uri("http://localhost:51169/Invoice")
' Render web URL to PDF
Private pdf As PdfDocument = renderer.RenderUrlAsPdf(uri)
' Export PDF
pdf.SaveAs("UrlToPdfExample.Pdf")
Dlaczego uwierzytelnienie sieciowe jest bardziej niezawodne niż wysyłanie formularza?
Uwierzytelnienie sieciowe oferuje kilka korzyści w porównaniu do wysyłania formularza HTML:
- Znormalizowany protokół: Używa nagłówków uwierzytelnienia HTTP zgodnych z standardami RFC
- Integracja z przeglądarką: Silnik renderujący Chrome bezproblemowo obsługuje uwierzytelnienie
- Zarządzanie sesjami: Automatyczna obsługa wyzwań uwierzytelniających i utrzymywanie sesji
- Bezpieczeństwo: Dane uwierzytelniające przesyłane bezpiecznie za pośrednictwem nagłówków zamiast danych formularza
- Kompatybilność: Działa z większością systemów uwierzytelniania przedsiębiorstwa (
Active Directory,LDAP)
Jakie dane uwierzytelniające są potrzebne do uwierzytelnienia sieciowego?
Różne typy uwierzytelnienia wymagają różnych danych uwierzytelniających:
// Basic Authentication (most common)
var basicAuth = new ChromeHttpLoginCredentials
{
NetworkUsername = "user@domain.com",
NetworkPassword = "password123",
AuthenticationType = ChromeHttpLoginCredentials.AuthType.Basic
};
// NTLM/Windows Authentication
var ntlmAuth = new ChromeHttpLoginCredentials
{
NetworkUsername = "DOMAIN\\username", // Include domain
NetworkPassword = "password123",
AuthenticationType = ChromeHttpLoginCredentials.AuthType.Ntlm
};
// Custom authentication headers
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CustomHttpHeaders.Add("X-API-Key", "your-api-key");
renderer.RenderingOptions.CustomHttpHeaders.Add("Authorization", "Bearer " + jwtToken);
// Basic Authentication (most common)
var basicAuth = new ChromeHttpLoginCredentials
{
NetworkUsername = "user@domain.com",
NetworkPassword = "password123",
AuthenticationType = ChromeHttpLoginCredentials.AuthType.Basic
};
// NTLM/Windows Authentication
var ntlmAuth = new ChromeHttpLoginCredentials
{
NetworkUsername = "DOMAIN\\username", // Include domain
NetworkPassword = "password123",
AuthenticationType = ChromeHttpLoginCredentials.AuthType.Ntlm
};
// Custom authentication headers
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CustomHttpHeaders.Add("X-API-Key", "your-api-key");
renderer.RenderingOptions.CustomHttpHeaders.Add("Authorization", "Bearer " + jwtToken);
Imports System.Collections.Generic
' Basic Authentication (most common)
Dim basicAuth As New ChromeHttpLoginCredentials With {
.NetworkUsername = "user@domain.com",
.NetworkPassword = "password123",
.AuthenticationType = ChromeHttpLoginCredentials.AuthType.Basic
}
' NTLM/Windows Authentication
Dim ntlmAuth As New ChromeHttpLoginCredentials With {
.NetworkUsername = "DOMAIN\username", ' Include domain
.NetworkPassword = "password123",
.AuthenticationType = ChromeHttpLoginCredentials.AuthType.Ntlm
}
' Custom authentication headers
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.CustomHttpHeaders.Add("X-API-Key", "your-api-key")
renderer.RenderingOptions.CustomHttpHeaders.Add("Authorization", "Bearer " & jwtToken)
Jak rozwiązywać problemy z błędami uwierzytelnienia?
Typowe problemy z uwierzytelnieniem i rozwiązania:
- 401 Nieautoryzowane: Sprawdź dane uwierzytelniające i typ uwierzytelnienia
- 403 Zabronione: Użytkownik uwierzytelniony, ale bez uprawnień
- Błędy Time-Out: Zwiększ
RenderDelaydla powolnych systemów uwierzytelniania - Błędy certyfikatu: Skonfiguruj odpowiednio ustawienia TLS/SSL
Włącz debugowanie, aby zdiagnozować problemy:
// Enable detailed logging
IronPdf.Logging.Logger.EnableDebugging = true;
IronPdf.Logging.Logger.LogFilePath = "IronPdf.log";
IronPdf.Logging.Logger.LoggingMode = IronPdf.Logging.Logger.LoggingModes.All;
// Test authentication
try
{
var pdf = renderer.RenderUrlAsPdf("https://secure.example.com");
pdf.SaveAs("authenticated.pdf");
}
catch (Exception ex)
{
Console.WriteLine($"Authentication failed: {ex.Message}");
// Check IronPdf.log for detailed error information
}
// Enable detailed logging
IronPdf.Logging.Logger.EnableDebugging = true;
IronPdf.Logging.Logger.LogFilePath = "IronPdf.log";
IronPdf.Logging.Logger.LoggingMode = IronPdf.Logging.Logger.LoggingModes.All;
// Test authentication
try
{
var pdf = renderer.RenderUrlAsPdf("https://secure.example.com");
pdf.SaveAs("authenticated.pdf");
}
catch (Exception ex)
{
Console.WriteLine($"Authentication failed: {ex.Message}");
// Check IronPdf.log for detailed error information
}
Imports IronPdf
Imports System
' Enable detailed logging
Logging.Logger.EnableDebugging = True
Logging.Logger.LogFilePath = "IronPdf.log"
Logging.Logger.LoggingMode = Logging.Logger.LoggingModes.All
' Test authentication
Try
Dim pdf = renderer.RenderUrlAsPdf("https://secure.example.com")
pdf.SaveAs("authenticated.pdf")
Catch ex As Exception
Console.WriteLine($"Authentication failed: {ex.Message}")
' Check IronPdf.log for detailed error information
End Try
Jak zalogować się używając formularza HTML?
Aby zalogować się, przesyłając dane do formularza HTML, użyj klasy ChromeHttpLoginCredentials. Zobacz API ChromeHttpLoginCredentials IronPDF.
Weź pod uwagę te punkty:
- Prześlij dane logowania do URL wskazanego w atrybucie ACTION formularza HTML. Ustaw to jako atrybut
LoginFormUrlHttpLoginCredentials. To może się różnić od URL, który chcesz wyrenderować jako PDF. - Wyślij dane reprezentujące każdy input i textarea w formularzu HTML. Atrybuty name definiują każdą zmienną (nie id).
- Niektóre strony aktywnie chronią przed logowaniem maszynowym.
Oto pełny przykład uwierzytelniania opartego na formularzach:
// Configure form-based login
var formLogin = new ChromeHttpLoginCredentials
{
LoginFormUrl = "https://example.com/login",
LoginFormData = new Dictionary<string, string>
{
{"username", "user@example.com"},
{"password", "securePassword123"},
{"rememberMe", "true"},
{"csrf_token", "abc123"} // Include any hidden fields
}
};
var renderer = new ChromePdfRenderer
{
LoginCredentials = formLogin,
RenderingOptions = new ChromePdfRenderOptions
{
RenderDelay = 3000, // Allow time for login redirect
EnableJavaScript = true
}
};
// The actual page you want to convert (after login)
var pdf = renderer.RenderUrlAsPdf("https://example.com/dashboard");
pdf.SaveAs("dashboard.pdf");
// Configure form-based login
var formLogin = new ChromeHttpLoginCredentials
{
LoginFormUrl = "https://example.com/login",
LoginFormData = new Dictionary<string, string>
{
{"username", "user@example.com"},
{"password", "securePassword123"},
{"rememberMe", "true"},
{"csrf_token", "abc123"} // Include any hidden fields
}
};
var renderer = new ChromePdfRenderer
{
LoginCredentials = formLogin,
RenderingOptions = new ChromePdfRenderOptions
{
RenderDelay = 3000, // Allow time for login redirect
EnableJavaScript = true
}
};
// The actual page you want to convert (after login)
var pdf = renderer.RenderUrlAsPdf("https://example.com/dashboard");
pdf.SaveAs("dashboard.pdf");
Imports System.Collections.Generic
' Configure form-based login
Dim formLogin As New ChromeHttpLoginCredentials With {
.LoginFormUrl = "https://example.com/login",
.LoginFormData = New Dictionary(Of String, String) From {
{"username", "user@example.com"},
{"password", "securePassword123"},
{"rememberMe", "true"},
{"csrf_token", "abc123"} ' Include any hidden fields
}
}
Dim renderer As New ChromePdfRenderer With {
.LoginCredentials = formLogin,
.RenderingOptions = New ChromePdfRenderOptions With {
.RenderDelay = 3000, ' Allow time for login redirect
.EnableJavaScript = True
}
}
' The actual page you want to convert (after login)
Dim pdf = renderer.RenderUrlAsPdf("https://example.com/dashboard")
pdf.SaveAs("dashboard.pdf")
Jakie dane formularza muszę pobrać?
Aby skutecznie przeprowadzić uwierzytelnienie przez formularze HTML, pobierz wszystkie wejścia formularza:
// Use this helper method to extract form fields
public Dictionary<string, string> ExtractFormFields(string loginPageHtml)
{
var formData = new Dictionary<string, string>();
var doc = new HtmlDocument();
doc.LoadHtml(loginPageHtml);
// Find all input fields
var inputs = doc.DocumentNode.SelectNodes("//input");
if (inputs != null)
{
foreach (var input in inputs)
{
string name = input.GetAttributeValue("name", "");
string value = input.GetAttributeValue("value", "");
string type = input.GetAttributeValue("type", "text");
if (!string.IsNullOrEmpty(name))
{
// Handle different input types
switch (type.ToLower())
{
case "checkbox":
if (input.Attributes["checked"] != null)
formData[name] = "on";
break;
case "radio":
if (input.Attributes["checked"] != null)
formData[name] = value;
break;
default:
formData[name] = value;
break;
}
}
}
}
// Don't forget select elements
var selects = doc.DocumentNode.SelectNodes("//select");
if (selects != null)
{
foreach (var select in selects)
{
string name = select.GetAttributeValue("name", "");
var selected = select.SelectSingleNode(".//option[@selected]");
if (selected != null && !string.IsNullOrEmpty(name))
{
formData[name] = selected.GetAttributeValue("value", "");
}
}
}
return formData;
}
// Use this helper method to extract form fields
public Dictionary<string, string> ExtractFormFields(string loginPageHtml)
{
var formData = new Dictionary<string, string>();
var doc = new HtmlDocument();
doc.LoadHtml(loginPageHtml);
// Find all input fields
var inputs = doc.DocumentNode.SelectNodes("//input");
if (inputs != null)
{
foreach (var input in inputs)
{
string name = input.GetAttributeValue("name", "");
string value = input.GetAttributeValue("value", "");
string type = input.GetAttributeValue("type", "text");
if (!string.IsNullOrEmpty(name))
{
// Handle different input types
switch (type.ToLower())
{
case "checkbox":
if (input.Attributes["checked"] != null)
formData[name] = "on";
break;
case "radio":
if (input.Attributes["checked"] != null)
formData[name] = value;
break;
default:
formData[name] = value;
break;
}
}
}
}
// Don't forget select elements
var selects = doc.DocumentNode.SelectNodes("//select");
if (selects != null)
{
foreach (var select in selects)
{
string name = select.GetAttributeValue("name", "");
var selected = select.SelectSingleNode(".//option[@selected]");
if (selected != null && !string.IsNullOrEmpty(name))
{
formData[name] = selected.GetAttributeValue("value", "");
}
}
}
return formData;
}
Imports HtmlAgilityPack
Public Function ExtractFormFields(loginPageHtml As String) As Dictionary(Of String, String)
Dim formData As New Dictionary(Of String, String)()
Dim doc As New HtmlDocument()
doc.LoadHtml(loginPageHtml)
' Find all input fields
Dim inputs = doc.DocumentNode.SelectNodes("//input")
If inputs IsNot Nothing Then
For Each input In inputs
Dim name As String = input.GetAttributeValue("name", "")
Dim value As String = input.GetAttributeValue("value", "")
Dim type As String = input.GetAttributeValue("type", "text")
If Not String.IsNullOrEmpty(name) Then
' Handle different input types
Select Case type.ToLower()
Case "checkbox"
If input.Attributes("checked") IsNot Nothing Then
formData(name) = "on"
End If
Case "radio"
If input.Attributes("checked") IsNot Nothing Then
formData(name) = value
End If
Case Else
formData(name) = value
End Select
End If
Next
End If
' Don't forget select elements
Dim selects = doc.DocumentNode.SelectNodes("//select")
If selects IsNot Nothing Then
For Each selectNode In selects
Dim name As String = selectNode.GetAttributeValue("name", "")
Dim selected = selectNode.SelectSingleNode(".//option[@selected]")
If selected IsNot Nothing AndAlso Not String.IsNullOrEmpty(name) Then
formData(name) = selected.GetAttributeValue("value", "")
End If
Next
End If
Return formData
End Function
Jak znaleźć poprawny URL akcji formularza?
URL akcji formularza jest kluczowy dla pomyślnego uwierzytelnienia:
public string ExtractFormAction(string loginPageUrl, string loginPageHtml)
{
var doc = new HtmlDocument();
doc.LoadHtml(loginPageHtml);
// Find the login form
var form = doc.DocumentNode.SelectSingleNode("//form[contains(@action, 'login') or contains(@id, 'login') or contains(@class, 'login')]");
if (form == null)
{
// Try finding any form with password field
form = doc.DocumentNode.SelectSingleNode("//form[.//input[@type='password']]");
}
if (form != null)
{
string action = form.GetAttributeValue("action", "");
// Resolve relative URLs
if (!string.IsNullOrEmpty(action))
{
var baseUri = new Uri(loginPageUrl);
var actionUri = new Uri(baseUri, action);
return actionUri.ToString();
}
}
// Default to the login page URL if no action found
return loginPageUrl;
}
public string ExtractFormAction(string loginPageUrl, string loginPageHtml)
{
var doc = new HtmlDocument();
doc.LoadHtml(loginPageHtml);
// Find the login form
var form = doc.DocumentNode.SelectSingleNode("//form[contains(@action, 'login') or contains(@id, 'login') or contains(@class, 'login')]");
if (form == null)
{
// Try finding any form with password field
form = doc.DocumentNode.SelectSingleNode("//form[.//input[@type='password']]");
}
if (form != null)
{
string action = form.GetAttributeValue("action", "");
// Resolve relative URLs
if (!string.IsNullOrEmpty(action))
{
var baseUri = new Uri(loginPageUrl);
var actionUri = new Uri(baseUri, action);
return actionUri.ToString();
}
}
// Default to the login page URL if no action found
return loginPageUrl;
}
Imports System
Public Function ExtractFormAction(loginPageUrl As String, loginPageHtml As String) As String
Dim doc As New HtmlDocument()
doc.LoadHtml(loginPageHtml)
' Find the login form
Dim form = doc.DocumentNode.SelectSingleNode("//form[contains(@action, 'login') or contains(@id, 'login') or contains(@class, 'login')]")
If form Is Nothing Then
' Try finding any form with password field
form = doc.DocumentNode.SelectSingleNode("//form[.//input[@type='password']]")
End If
If form IsNot Nothing Then
Dim action As String = form.GetAttributeValue("action", "")
' Resolve relative URLs
If Not String.IsNullOrEmpty(action) Then
Dim baseUri As New Uri(loginPageUrl)
Dim actionUri As New Uri(baseUri, action)
Return actionUri.ToString()
End If
End If
' Default to the login page URL if no action found
Return loginPageUrl
End Function
Jakie są typowe problemy z uwierzytelnianiem opartym na formularzach?
- Tokeny CSRF: Wiele formularzy zawiera wygasające tokeny antyfałszywki
- Walidacja JavaScript: Niektóre formularze wymagają wykonania JavaScript
- Wielopoziomowe uwierzytelnienie: Formularze wymagające kilku stron
- Ochrona CAPTCHA: Wyzwania weryfikacji ludzkiej
- Wygasanie sesji: Sesje logowania wygasające szybko
Jak obsługiwać ochronę przed botami?
Nowoczesne strony wdrażają ochronę przed zautomatyzowanymi logowaniami:
// Strategies for handling anti-bot measures
var renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
// Mimic real browser behavior
ViewPortWidth = 1920,
ViewPortHeight = 1080,
EnableJavaScript = true,
RenderDelay = 5000, // Wait for JavaScript
// Set a real user agent
CustomHttpHeaders = new Dictionary<string, string>
{
{"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
}
}
};
// For sites with rate limiting, add delays between requests
System.Threading.Thread.Sleep(2000);
// Strategies for handling anti-bot measures
var renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
// Mimic real browser behavior
ViewPortWidth = 1920,
ViewPortHeight = 1080,
EnableJavaScript = true,
RenderDelay = 5000, // Wait for JavaScript
// Set a real user agent
CustomHttpHeaders = new Dictionary<string, string>
{
{"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
}
}
};
// For sites with rate limiting, add delays between requests
System.Threading.Thread.Sleep(2000);
' Strategies for handling anti-bot measures
Dim renderer = New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
' Mimic real browser behavior
.ViewPortWidth = 1920,
.ViewPortHeight = 1080,
.EnableJavaScript = True,
.RenderDelay = 5000, ' Wait for JavaScript
' Set a real user agent
.CustomHttpHeaders = New Dictionary(Of String, String) From {
{"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
}
}
}
' For sites with rate limiting, add delays between requests
System.Threading.Thread.Sleep(2000)
Dla kompleksowych wskazówek dotyczących konwersji HTML na PDF, w tym złożonych scenariuszy uwierzytelniania, odwiedź poradnik HTML na PDF.
Jak obsługiwać uwierzytelnienie MVC?
Poniższe obejście renderuje widok .NET MVC do ciągu programatycznie, unikając logowań MVC przy wiernym renderowaniu widoków. To podejście działa dobrze przy konwersji CSHTML do PDF w MVC Core lub MVC Framework.
// Converts an MVC partial view to a string
public static string RenderPartialViewToString(this Controller controller, string viewPath, object model = null)
{
try
{
// Set the model
var context = controller.ControllerContext;
controller.ViewData.Model = model;
using (var sw = new StringWriter())
{
// Find the partial view
var viewResult = ViewEngines.Engines.FindPartialView(context, viewPath);
if (viewResult.View == null)
{
throw new Exception($"Partial view {viewPath} could not be found.");
}
// Create a view context
var viewContext = new ViewContext(context, viewResult.View, context.Controller.ViewData, context.Controller.TempData, sw);
// Render the view
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(context, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
catch (Exception ex)
{
// Return error message if there is an exception
return ex.Message;
}
}
// Usage in an MVC Controller
public ActionResult GeneratePdf()
{
// Render authenticated view to string
var model = new InvoiceViewModel { /* populate model */ };
string html = this.RenderPartialViewToString("~/Views/Invoice/Details.cshtml", model);
// Convert to PDF
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Return PDF file
return File(pdf.BinaryData, "application/pdf", "invoice.pdf");
}
// Converts an MVC partial view to a string
public static string RenderPartialViewToString(this Controller controller, string viewPath, object model = null)
{
try
{
// Set the model
var context = controller.ControllerContext;
controller.ViewData.Model = model;
using (var sw = new StringWriter())
{
// Find the partial view
var viewResult = ViewEngines.Engines.FindPartialView(context, viewPath);
if (viewResult.View == null)
{
throw new Exception($"Partial view {viewPath} could not be found.");
}
// Create a view context
var viewContext = new ViewContext(context, viewResult.View, context.Controller.ViewData, context.Controller.TempData, sw);
// Render the view
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(context, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
catch (Exception ex)
{
// Return error message if there is an exception
return ex.Message;
}
}
// Usage in an MVC Controller
public ActionResult GeneratePdf()
{
// Render authenticated view to string
var model = new InvoiceViewModel { /* populate model */ };
string html = this.RenderPartialViewToString("~/Views/Invoice/Details.cshtml", model);
// Convert to PDF
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Return PDF file
return File(pdf.BinaryData, "application/pdf", "invoice.pdf");
}
Imports System
Imports System.IO
Imports System.Web.Mvc
Imports IronPdf
' Converts an MVC partial view to a string
Public Module ControllerExtensions
<System.Runtime.CompilerServices.Extension>
Public Function RenderPartialViewToString(controller As Controller, viewPath As String, Optional model As Object = Nothing) As String
Try
' Set the model
Dim context = controller.ControllerContext
controller.ViewData.Model = model
Using sw As New StringWriter()
' Find the partial view
Dim viewResult = ViewEngines.Engines.FindPartialView(context, viewPath)
If viewResult.View Is Nothing Then
Throw New Exception($"Partial view {viewPath} could not be found.")
End If
' Create a view context
Dim viewContext As New ViewContext(context, viewResult.View, context.Controller.ViewData, context.Controller.TempData, sw)
' Render the view
viewResult.View.Render(viewContext, sw)
viewResult.ViewEngine.ReleaseView(context, viewResult.View)
Return sw.GetStringBuilder().ToString()
End Using
Catch ex As Exception
' Return error message if there is an exception
Return ex.Message
End Try
End Function
End Module
' Usage in an MVC Controller
Public Class InvoiceController
Inherits Controller
Public Function GeneratePdf() As ActionResult
' Render authenticated view to string
Dim model As New InvoiceViewModel() ' populate model
Dim html As String = Me.RenderPartialViewToString("~/Views/Invoice/Details.cshtml", model)
' Convert to PDF
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
' Return PDF file
Return File(pdf.BinaryData, "application/pdf", "invoice.pdf")
End Function
End Class
Dlaczego renderować widoki do ciągu zamiast bezpośrednio konwertować?
Renderowanie widoków MVC do ciągu oferuje kilka kluczowych korzyści:
- Kontekst uwierzytelnienia: Widoki renderowane w kontekście zalogowanego użytkownika
- Pełny pipeline MVC: Wszystkie funkcje MVC działają, w tym
ViewBag,TempData, iHtmlasystenci - Wsparcie dla układów: Strony główne i układy renderują się poprawnie
- Więzy modeli: Zaawansowane modele widoków działają bezproblemowo
- Filtry akcji: Filtry bezpieczeństwa i logowania działają normalnie
Jakie są zalety tego obejścia MVC?
Podejście MVC polegające na renderowaniu ciągu oferuje:
- Bezpieczeństwo: Brak konieczności ujawniania wewnętrznych URL-i lub omijania uwierzytelnienia
- Wydajność: Unikanie dodatkowych żądań HTTP
- Spójność: Tożsamy output z tym, co widzą użytkownicy w przeglądarkach
- Elastyczność: Modyfikacja HTML przed konwersją PDF
- Testowanie: Łatwe testowanie jednostkowe generacji HTML
Jak przekazywać modele do wyrenderowanego widoku?
Oto kompletny przykład złożonego modelu:
public class InvoiceController : Controller
{
private readonly IInvoiceService _invoiceService;
public async Task<ActionResult> DownloadInvoicePdf(int invoiceId)
{
// Load data within authenticated context
var invoice = await _invoiceService.GetInvoiceAsync(invoiceId);
if (invoice == null || invoice.UserId != User.Identity.GetUserId())
{
return HttpNotFound();
}
// Create view model
var viewModel = new InvoiceDetailsViewModel
{
Invoice = invoice,
Company = await _invoiceService.GetCompanyDetailsAsync(),
LineItems = await _invoiceService.GetLineItemsAsync(invoiceId),
TaxDetails = await _invoiceService.GetTaxDetailsAsync(invoiceId)
};
// Render to HTML string
string html = this.RenderPartialViewToString("~/Views/Invoice/DetailsPdf.cshtml", viewModel);
// Add custom styling for PDF
html = $@"
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{ background-color: #f0f0f0; padding: 20px; }}
.line-items {{ width: 100%; border-collapse: collapse; }}
.line-items th, .line-items td {{ border: 1px solid #ddd; padding: 8px; }}
</style>
</head>
<body>
{html}
</body>
</html>";
// Convert to PDF with options
var renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
MarginTop = 20,
MarginBottom = 20,
MarginLeft = 10,
MarginRight = 10,
PrintHtmlBackgrounds = true
}
};
var pdf = renderer.RenderHtmlAsPdf(html);
// Add metadata
pdf.MetaData.Author = "Invoice System";
pdf.MetaData.Title = $"Invoice #{invoice.Number}";
pdf.MetaData.CreationDate = DateTime.Now;
return File(pdf.BinaryData, "application/pdf", $"Invoice-{invoice.Number}.pdf");
}
}
public class InvoiceController : Controller
{
private readonly IInvoiceService _invoiceService;
public async Task<ActionResult> DownloadInvoicePdf(int invoiceId)
{
// Load data within authenticated context
var invoice = await _invoiceService.GetInvoiceAsync(invoiceId);
if (invoice == null || invoice.UserId != User.Identity.GetUserId())
{
return HttpNotFound();
}
// Create view model
var viewModel = new InvoiceDetailsViewModel
{
Invoice = invoice,
Company = await _invoiceService.GetCompanyDetailsAsync(),
LineItems = await _invoiceService.GetLineItemsAsync(invoiceId),
TaxDetails = await _invoiceService.GetTaxDetailsAsync(invoiceId)
};
// Render to HTML string
string html = this.RenderPartialViewToString("~/Views/Invoice/DetailsPdf.cshtml", viewModel);
// Add custom styling for PDF
html = $@"
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{ background-color: #f0f0f0; padding: 20px; }}
.line-items {{ width: 100%; border-collapse: collapse; }}
.line-items th, .line-items td {{ border: 1px solid #ddd; padding: 8px; }}
</style>
</head>
<body>
{html}
</body>
</html>";
// Convert to PDF with options
var renderer = new ChromePdfRenderer
{
RenderingOptions = new ChromePdfRenderOptions
{
MarginTop = 20,
MarginBottom = 20,
MarginLeft = 10,
MarginRight = 10,
PrintHtmlBackgrounds = true
}
};
var pdf = renderer.RenderHtmlAsPdf(html);
// Add metadata
pdf.MetaData.Author = "Invoice System";
pdf.MetaData.Title = $"Invoice #{invoice.Number}";
pdf.MetaData.CreationDate = DateTime.Now;
return File(pdf.BinaryData, "application/pdf", $"Invoice-{invoice.Number}.pdf");
}
}
Imports System.Threading.Tasks
Imports System.Web.Mvc
Public Class InvoiceController
Inherits Controller
Private ReadOnly _invoiceService As IInvoiceService
Public Async Function DownloadInvoicePdf(invoiceId As Integer) As Task(Of ActionResult)
' Load data within authenticated context
Dim invoice = Await _invoiceService.GetInvoiceAsync(invoiceId)
If invoice Is Nothing OrElse invoice.UserId <> User.Identity.GetUserId() Then
Return HttpNotFound()
End If
' Create view model
Dim viewModel As New InvoiceDetailsViewModel With {
.Invoice = invoice,
.Company = Await _invoiceService.GetCompanyDetailsAsync(),
.LineItems = Await _invoiceService.GetLineItemsAsync(invoiceId),
.TaxDetails = Await _invoiceService.GetTaxDetailsAsync(invoiceId)
}
' Render to HTML string
Dim html As String = Me.RenderPartialViewToString("~/Views/Invoice/DetailsPdf.cshtml", viewModel)
' Add custom styling for PDF
html = $"
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{ background-color: #f0f0f0; padding: 20px; }}
.line-items {{ width: 100%; border-collapse: collapse; }}
.line-items th, .line-items td {{ border: 1px solid #ddd; padding: 8px; }}
</style>
</head>
<body>
{html}
</body>
</html>"
' Convert to PDF with options
Dim renderer As New ChromePdfRenderer With {
.RenderingOptions = New ChromePdfRenderOptions With {
.MarginTop = 20,
.MarginBottom = 20,
.MarginLeft = 10,
.MarginRight = 10,
.PrintHtmlBackgrounds = True
}
}
Dim pdf = renderer.RenderHtmlAsPdf(html)
' Add metadata
pdf.MetaData.Author = "Invoice System"
pdf.MetaData.Title = $"Invoice #{invoice.Number}"
pdf.MetaData.CreationDate = DateTime.Now
Return File(pdf.BinaryData, "application/pdf", $"Invoice-{invoice.Number}.pdf")
End Function
End Class
Przed wdrożeniem jakiegokolwiek rozwiązania uwierzytelniania, upewnij się, że poprawnie zainstalowałeś IronPDF i skonfigurowałeś swoje klucze licencyjne.
Gotowy, aby sprawdzić, co jeszcze możesz zrobić? Odwiedź naszą stronę z poradnikami: Konwertuj PDF-y.
Często Zadawane Pytania
How can I convert HTML to PDF when the content is behind a login form?
IronPDF provides multiple approaches for converting HTML to PDF behind login authentication. You can use the ChromeHttpLoginCredentials API for TLS network authentication, or download the HTML content using System.Net.WebClient or HttpClient with appropriate authentication headers before converting it to PDF with IronPDF.
What is ChromeHttpLoginCredentials and how do I use it?
ChromeHttpLoginCredentials is IronPDF's API for handling network authentication. You can use it by setting the LoginCredentials property on ChromePdfRenderer with your username and password, allowing IronPDF to automatically authenticate when rendering password-protected URLs to PDF.
Can I handle HTML form-based logins for PDF conversion?
Yes, IronPDF supports HTML form-based logins. The recommended approach is to use System.Net.WebClient or HttpClient to handle the login process, download the authenticated HTML content, and then use IronPDF's RenderHtmlAsPdf method to convert the downloaded HTML to PDF.
How do I download HTML assets like images and stylesheets from authenticated pages?
You can use HtmlAgilityPack to parse the downloaded HTML and extract asset URLs like images and stylesheets. Then use System.Net.WebClient to download each asset with the same authentication headers before converting the complete HTML package to PDF with IronPDF.
What's the best practice for handling authentication tokens or headers?
When using IronPDF with authentication tokens, download the HTML using HttpClient or WebClient with your authentication headers (such as Bearer tokens). Once you have the authenticated HTML content in memory or saved to disk, use IronPDF's ChromePdfRenderer to convert it to PDF.
Is there a workaround for MVC login authentication?
Yes, IronPDF provides workarounds for MVC login authentication scenarios. The recommended approach is to first authenticate and download the HTML content using standard .NET HTTP clients, then pass the authenticated HTML directly to IronPDF's rendering engine rather than having IronPDF handle the authentication.

