Condividi tramite


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 funzione InternetConnect . Attualmente l'autenticazione del 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 invia una o più intestazioni di risposta, ovvero Proxy-Authentication (per l'autenticazione 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 sono supportati più schemi di autenticazione, il server restituisce più intestazioni di risposta di autenticazione. Il valore dell'area di autenticazione è distinzione tra maiuscole e minuscole e definisce uno spazio di protezione nel proxy o nel server. Ad esempio, l'intestazione "WWW-Authentication: 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 intestazione di autorizzazione con la richiesta. L'intestazione Di autorizzazione contiene lo schema di autenticazione e la risposta appropriata richiesta da tale schema. Ad esempio, l'intestazione "Autorizzazione: nome utente di base <:password>" verrà aggiunta alla richiesta e nuovamente inviata al server se il client ha ricevuto l'intestazione di risposta autenticata "WWW-Authentication: 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 di risposta alla sfida, che consentono un formato di risposta alla sfida.

Lo schema di autenticazione di base è basato sul modello che un client deve autenticarsi con un nome utente e una password per ogni area di autenticazione. Il server esegue il servizio della richiesta se viene eseguito di nuovo con un'intestazione di autorizzazione che include un nome utente e una password validi.

Gli schemi di risposta di sfida consentono un'autenticazione più sicura. Se una richiesta richiede l'autenticazione usando uno schema di risposta alla sfida, il codice di stato appropriato e le intestazioni Di autenticazione 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 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.

Schema Tipo DLL Descrizione
Basic (cleartext) basic Wininet.dll Usa una stringa codificata base64 contenente il nome utente e la password.
Digest challenge-response Digest.dll Schema di risposta alla sfida che verifica l'uso di un valore nonce (stringa di dati specificata dal server). Una risposta valida contiene un checksum del nome utente, della password, del valore nonce specificato, del metodo HTTP e dell'URI (Uniform Resource Identifier) richiesto. Il supporto per l'autenticazione del digest è stato introdotto in Microsoft Internet Explorer 5.
NT LAN Manager (NTLM) challenge-response Winsspi.dll Schema di risposta alla sfida che basa la sfida sul nome utente.
Microsoft Network (MSN) challenge-response Msnsspc.dll Schema di autenticazione di Microsoft Network.
Autenticazione password distribuita (DPA) challenge-response Msapsspc.dll Analogamente all'autenticazione MSN e viene usata anche da Microsoft Network.
Autenticazione passphrase remota (RPA) Compuserve Rpawinet.dll, da.dll Schema di autenticazione CompuServe. Per altre informazioni, vedere Le specifiche del meccanismo RPA.

 

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 di 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 è gestita, il processo di autenticazione deve essere riavviato con il proxy o il server.

Le funzioni InternetOpenUrl e HttpSendRequest completano 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, ProxyServer e ProxyOverride. Questi valori si trovano in HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings.

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 Flags .

  • 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 modello di autenticazione o URL a blocchi.

  • 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 usa una stringa di autenticazione http standard. Tutti i dati che sembrano essere un'area di autenticazione sono dati specifici dello schema.

  • PLUGIN_AUTH_FLAGS_KEEP_ALIVE_NOT_REQUIRED (value=0x10)

    Questa DLL non richiede una connessione persistente per la sequenza di risposta di sfida.

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, DLLFile e un valore DWORD. DLLFile deve essere impostato su Winsspi.dll e i flag devono essere impostati su 0x08.

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 disponibili nel server. WinINet sceglie il primo metodo che riconosce.

L'autenticazione di base fornisce sicurezza debole a meno che il canale non sia prima crittografato con SSL o PCT.

La funzione InternetErrorDlg può essere usata per ottenere il nome utente e i dati delle password dall'utente oppure un'interfaccia utente personalizzata può essere progettata per ottenere i dati.

Un'interfaccia personalizzata può usare la funzione InternetSetOption per impostare i valori di 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 deve includere una o più intestazioni di risposta Proxy-Authenticate. Queste intestazioni includono i metodi di autenticazione disponibili dal proxy. WinINet sceglie il primo metodo che riconosce.

La funzione InternetErrorDlg può essere usata per ottenere il nome utente e i dati delle password dall'utente oppure è possibile progettare un'interfaccia utente personalizzata.

Un'interfaccia personalizzata può usare la funzione InternetSetOption per impostare i valori di INTERNET_OPTION_PROXY_PASSWORD e INTERNET_OPTION_PROXY_USERNAME e quindi inviare nuovamente la richiesta al proxy.

Se non è 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 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 handle DELL'interfaccia DELLA RETE PER individuare errori nascosti, ad esempio codici di stato da 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 intestazioni WWW-Authenticate o Proxy-Authenticate personalizzate, è necessario impostare il flag di INTERNET_FLAG_NO_AUTH per disabilitare l'autenticazione.

Nell'esempio seguente viene illustrato come è possibile 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 la presenza di eventuali errori nascosti nelle intestazioni. 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 di dati appropriata per l'errore e archivii i risultati della finestra di dialogo nell'handle DI RETE.

Il codice di esempio seguente mostra come l'autenticazione può essere gestita tramite 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 da un servizio. Per le implementazioni del server o i servizi, usare i servizi HTTP di Microsoft Windows (WinHTTP).