Gestione dell'autenticazione
Alcuni proxy e server richiedono l'autenticazione prima di concedere l'accesso alle risorse su Internet. Le funzioni WinINet supportano l'autenticazione del server e del proxy per le sessioni HTTP. L'autenticazione dei server FTP deve essere gestita dalla funzioneInternetConnect. Attualmente, l'autenticazione gateway FTP non è supportata.
Informazioni sull'autenticazione HTTP
Se è necessaria l'autenticazione, l'applicazione client riceve un codice di stato 401, se il server richiede l'autenticazione o 407, se il proxy richiede l'autenticazione. Con il codice di stato, il proxy o il server inviano una o più intestazioni di risposta per l'autenticazione:Proxy-Authenticate (per l'autenticazione del proxy) o WWW-Authenticate (per l'autenticazione del server).
Ogni intestazione di risposta di autenticazione contiene uno schema di autenticazione disponibile e un'area di autenticazione. Se vengono supportati più schemi di autenticazione, il server restituisce diverse intestazioni di risposta per l'autenticazione. Il valore del realm fa distinzione tra maiuscole e minuscole e definisce uno spazio di protezione nel proxy o nel server. Ad esempio, l'intestazione "WWW-Authenticate: Basic Realm="example"" è un esempio di intestazione restituita quando è necessaria l'autenticazione del server.
L'applicazione client che ha inviato la richiesta può autenticarsi includendo un campo di Intestazione di Autorizzazione nella richiesta. L'intestazione Authorization conterrà lo schema di autenticazione e la risposta appropriata richiesta da tale schema. Ad esempio, l'intestazione "Authorization: Basic <username:password>" verrebbe aggiunta alla richiesta e inviata nuovamente al server se il client ha ricevuto l'intestazione di risposta di autenticazione "WWW-Authenticate: Basic Realm="example"".
Esistono due tipi generali di schemi di autenticazione:
- Schema di autenticazione di base, in cui il nome utente e la password vengono inviati in testo non crittografato al server.
- Schemi sfida-risposta, che consentono un formato sfida-risposta.
Lo schema di autenticazione di base si basa sul modello che un client deve autenticarsi con un nome utente e una password per ogni area di autenticazione. Il server esegue la richiesta se viene reinviato con un'intestazione di autorizzazione che include un nome utente e una password validi.
Gli schemi challenge-response consentono un'autenticazione più sicura. Se una richiesta richiede l'autenticazione usando uno schema challenge-response, il codice di stato appropriato e le intestazioni Authenticate vengono restituite al client. Il client deve quindi inviare nuovamente la richiesta con una negoziazione. Il server restituirà un codice di stato appropriato con una richiesta di verifica e il client richiederà quindi di inviare nuovamente la richiesta con la risposta appropriata per ottenere il servizio richiesto.
Nella tabella seguente sono elencati gli schemi di autenticazione, il tipo di autenticazione, la DLL che li supporta e una descrizione dello schema.
Per qualsiasi elemento diverso dall'autenticazione di base, le chiavi del Registro di sistema devono essere configurate oltre all'installazione della DLL appropriata.
Se è necessaria l'autenticazione, il flag di INTERNET_FLAG_KEEP_CONNECTION deve essere usato nella chiamata a HttpOpenRequest. Il flag INTERNET_FLAG_KEEP_CONNECTION è necessario per NTLM e altri tipi di autenticazione per mantenere la connessione durante il completamento del processo di autenticazione. Se la connessione non viene mantenuta, il processo di autenticazione deve essere riavviato con il proxy o il server.
Le funzioni InternetOpenUrl e httpSendRequestcompletano correttamente anche quando è necessaria l'autenticazione. La differenza è che i dati restituiti nei file di intestazione e InternetReadFile riceveranno una pagina HTML che informa l'utente del codice di stato.
Registrazione delle chiavi di autenticazione
INTERNET_OPEN_TYPE_PRECONFIG esamina i valori del Registro di sistema ProxyEnable, ProxyServere ProxyOverride. Questi valori si trovano in HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Impostazioni Internet.
Per gli schemi di autenticazione diversi da Basic, è necessario aggiungere una chiave al Registro di sistema in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Security. Un valore DWORD, Flag, deve essere impostato con il valore appropriato. L'elenco seguente mostra i valori possibili per il valore flag di.
PLUGIN_AUTH_FLAGS_UNIQUE_CONTEXT_PER_TCPIP (value=0x01)
Ogni socket TCP/IP (Transmission Control Protocol/Internet Protocol) contiene un contesto diverso. In caso contrario, viene passato un nuovo contesto per ogni ambito o modello di URL di blocco.
PLUGIN_AUTH_FLAGS_CAN_HANDLE_UI (value=0x02)
Questa DLL può gestire il proprio input utente.
PLUGIN_AUTH_FLAGS_CAN_HANDLE_NO_PASSWD (value=0x04)
Questa DLL potrebbe essere in grado di eseguire un'autenticazione senza richiedere all'utente una password.
PLUGIN_AUTH_FLAGS_NO_REALM (value=0x08)
Questa DLL non utilizza una stringa di ambito di autenticazione HTTP standard. Tutti i dati che sembrano essere un "realm" sono dati specifici dello schema.
PLUGIN_AUTH_FLAGS_KEEP_ALIVE_NOT_REQUIRED (value=0x10)
Questa DLL non richiede una connessione permanente per la sequenza di risposta di verifica.
Ad esempio, per aggiungere l'autenticazione NTLM, è necessario aggiungere la chiave NTLM a HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Security. In HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Security\NTLM, è necessario aggiungere il valore stringa DLLFilee un valore DWORDFlag. DLLFile deve essere impostato su Winsspi.dlle i Flag devono essere impostati su 0x08.
L'autenticazione del server
Quando un server riceve una richiesta che richiede l'autenticazione, il server restituisce un messaggio di codice di stato 401. In tale messaggio, il server deve includere una o più intestazioni di risposta WWW-Authenticate. Queste intestazioni includono i metodi di autenticazione che il server ha a disposizione. WinINet sceglie il primo metodo riconosciuto.
L'autenticazione di base offre una sicurezza debole a meno che il canale non sia prima crittografato con SSL o PCT.
La funzione InternetErrorDlg può essere usata per ottenere i dati di nome utente e password dall'utente oppure è possibile progettare un'interfaccia utente personalizzata per ottenere i dati.
Un'interfaccia personalizzata può usare la funzione di InternetSetOption per impostare i valori INTERNET_OPTION_PASSWORD e INTERNET_OPTION_USERNAME e quindi inviare nuovamente la richiesta al server.
Autenticazione proxy
Quando un client tenta di usare un proxy che richiede l'autenticazione, il proxy restituisce un messaggio di codice di stato 407 al client. In tale messaggio, il proxy dovrebbe includere una o più intestazioni di risposta denominate Proxy-Authenticate. Queste intestazioni includono i metodi di autenticazione disponibili tramite il proxy. WinINet sceglie il primo metodo riconosciuto.
La funzioneInternetErrorDlgpuò essere utilizzata per ottenere i dati di nome utente e password dall'utente oppure è possibile progettare un'interfaccia utente personalizzata.
Un'interfaccia personalizzata può usare la funzioneInternetSetOption per impostare i valori INTERNET_OPTION_PROXY_PASSWORD e INTERNET_OPTION_PROXY_USERNAME e quindi inviare nuovamente la richiesta al proxy.
Se non viene impostato alcun nome utente proxy e password, WinINet tenta di usare il nome utente e la password per il server. Questo comportamento consente ai client di implementare la stessa interfaccia utente personalizzata usata per gestire l'autenticazione del server.
Gestione dell'autenticazione HTTP
L'autenticazione HTTP può essere gestita con InternetErrorDlg o con una funzione personalizzata che usa InternetSetOption o aggiunge le proprie intestazioni di autenticazione. InternetErrorDlg può esaminare le intestazioni associate a un HINTERNET per trovare errori nascosti, ad esempio i codici di stato di un proxy o un server. InternetSetOption può essere usato per impostare il nome utente e la password per il proxy e il server. Per l'autenticazione MSN e DPA, è necessario utilizzare internetErrorDlg per impostare il nome utente e la password.
Per qualsiasi funzione personalizzata che aggiunge le proprie intestazioni WWW-Authenticate o Proxy-Authenticate, è necessario impostare il flag INTERNET_FLAG_NO_AUTH per disabilitare l'autenticazione.
Nell'esempio seguente viene illustrato come usare InternetErrorDlg per gestire l'autenticazione HTTP.
HINTERNET hOpenHandle, hConnectHandle, hResourceHandle;
DWORD dwError, dwErrorCode;
HWND hwnd = GetConsoleWindow();
hOpenHandle = InternetOpen(TEXT("Example"),
INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, 0);
hConnectHandle = InternetConnect(hOpenHandle,
TEXT("www.server.com"),
INTERNET_INVALID_PORT_NUMBER,
NULL,
NULL,
INTERNET_SERVICE_HTTP,
0,0);
hResourceHandle = HttpOpenRequest(hConnectHandle, TEXT("GET"),
TEXT("/premium/default.htm"),
NULL, NULL, NULL,
INTERNET_FLAG_KEEP_CONNECTION, 0);
resend:
HttpSendRequest(hResourceHandle, NULL, 0, NULL, 0);
// dwErrorCode stores the error code associated with the call to
// HttpSendRequest.
dwErrorCode = hResourceHandle ? ERROR_SUCCESS : GetLastError();
dwError = InternetErrorDlg(hwnd, hResourceHandle, dwErrorCode,
FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,
NULL);
if (dwError == ERROR_INTERNET_FORCE_RETRY)
goto resend;
// Insert code to read the data from the hResourceHandle
// at this point.
Nell'esempio dwErrorCode viene usato per archiviare eventuali errori associati alla chiamata a HttpSendRequest. httpSendRequest viene completato correttamente, anche se il proxy o il server richiede l'autenticazione. Quando il flag FLAGS_ERROR_UI_FILTER_FOR_ERRORS viene passato a InternetErrorDlg, la funzione controlla le intestazioni per eventuali errori nascosti. Questi errori nascosti includono eventuali richieste di autenticazione. InternetErrorDlg visualizza la finestra di dialogo appropriata per richiedere all'utente i dati necessari. Anche i flag FLAGS_ERROR_UI_FLAGS_GENERATE_DATA e FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS devono essere passati a InternetErrorDlg, in modo che la funzione costruisca la struttura dati appropriata per l'errore e salvi i risultati della finestra di dialogo nell'handle HINTERNET.
Nel codice di esempio seguente viene illustrato come gestire l'autenticazione usando InternetSetOption.
HINTERNET hOpenHandle, hResourceHandle, hConnectHandle;
DWORD dwStatus;
DWORD dwStatusSize = sizeof(dwStatus);
char strUsername[64], strPassword[64];
// Normally, hOpenHandle, hResourceHandle,
// and hConnectHandle need to be properly assigned.
hOpenHandle = InternetOpen(TEXT("Example"),
INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, 0);
hConnectHandle = InternetConnect(hOpenHandle,
TEXT("www.server.com"),
INTERNET_INVALID_PORT_NUMBER,
NULL,
NULL,
INTERNET_SERVICE_HTTP,
0,0);
hResourceHandle = HttpOpenRequest(hConnectHandle, TEXT("GET"),
TEXT("/premium/default.htm"),
NULL, NULL, NULL,
INTERNET_FLAG_KEEP_CONNECTION,
0);
resend:
HttpSendRequest(hResourceHandle, NULL, 0, NULL, 0);
HttpQueryInfo(hResourceHandle, HTTP_QUERY_FLAG_NUMBER |
HTTP_QUERY_STATUS_CODE, &dwStatus, &dwStatusSize, NULL);
switch (dwStatus)
{
// cchUserLength is the length of strUsername and
// cchPasswordLength is the length of strPassword.
DWORD cchUserLength, cchPasswordLength;
case HTTP_STATUS_PROXY_AUTH_REQ: // Proxy Authentication Required
// Insert code to set strUsername and strPassword.
// Insert code to safely determine cchUserLength and
// cchPasswordLength. Insert appropriate error handling code.
InternetSetOption(hResourceHandle,
INTERNET_OPTION_PROXY_USERNAME,
strUsername,
cchUserLength+1);
InternetSetOption(hResourceHandle,
INTERNET_OPTION_PROXY_PASSWORD,
strPassword,
cchPasswordLength+1);
goto resend;
break;
case HTTP_STATUS_DENIED: // Server Authentication Required.
// Insert code to set strUsername and strPassword.
// Insert code to safely determine cchUserLength and
// cchPasswordLength. Insert error handling code as
// appropriate.
InternetSetOption(hResourceHandle, INTERNET_OPTION_USERNAME,
strUsername, cchUserLength+1);
InternetSetOption(hResourceHandle, INTERNET_OPTION_PASSWORD,
strPassword, cchPasswordLength+1);
goto resend;
break;
}
// Insert code to read the data from the hResourceHandle
// at this point.
Nota
WinINet non supporta le implementazioni del server. Inoltre, non deve essere usato tramite un servizio. Per le implementazioni del server o i servizi, usare Servizi HTTP Di Microsoft Windows (WinHTTP).