Having a secure website is essential if you are using HTTP to connect to, say, a corporate database. Windows NT and 2000 websites can be secured using the following:
If an HTTP request fails authentication, an error 401 will be returned if the error originates in a web server, or 407 for a proxy server authentication failure. These errors are returned in HTTP headers from the server. If your application receives a 401 or 407 error, a valid username and password should be supplied. The type of authentication can be configured in Microsoft Internet Information Server (IIS) for each website or virtual directory on a server. Further, an anonymous login can be specified, so that an unrecognized user can login using the specified login. This login name is usually based on the server name, for example, IUSR_MYSERVER, where MYSERVER is the name of the server IIS is installed on. With IIS, once the type of authentication has been configured, NTFS security is applied to the files in the website, and this controls who has what type of access to the files or directories. The following two methods can be used to handle authentication errors:
You will need to specify the INTERNET_FLAG_KEEP_CONNECTION option when calling HttpOpenRequest so that the security options can be maintained between HTTP requests. hHttpRequest = HttpOpenRequest(hHttpSession, NULL, // verb is 'GET' crackedURL.lpszUrlPath, NULL, // default version NULL, // no referrer NULL, // only accept text/* files INTERNET_FLAG_KEEP_CONNECTION, 0); // no context for call backs One of the problems with using authentication with IIS is finding out which user is making the HTTP requests. Therefore, when testing your authentication code you should turn on logging, and look for the requests in the IIS logs. In the following examples, the first request was made with no username specified (-), and the second used "Administrator." 192.168.0.221, -, 28/02/00, 14:52:41, W3SVC1, SPL_WEB, 192.168.0.2, 71, 363, 761, 401, 5, GET, / site, -, 192.168.0.221, administrator, 28/02/00, 14:52:49, W3SVC1, SPL_WEB, 192.168.0.2, 1502, 414, 300, 302, 0, GET, /site/, -, Authentication with InternetErrorDlgThe function InternetErrorDlg can be used in a variety of ways to correct errors with HTTP requests. For example, the function can be used to prompt the user for a username and password in the event of an authentication error. The code fragment in Listing 8.3 calls HttpSendRequest, and then calls InternetErrorDlg with the following options:
Listing 8.3 Correcting authentication errors with InternetErrorDlgresend: if(!HttpSendRequest(hHttpRequest, NULL, 0, // no headers 0, 0)) // no optional data { cout _T("Could not send request ") GetLastError(); goto cleanUp; } DWORD dwErrorCode, dwError; dwErrorCode = hHttpRequest ? ERROR_SUCCESS : GetLastError(); dwError = InternetErrorDlg(GetFocus(), hHttpRequest, 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; // now read the data from the request // using InternetReadFile. Notice that when an authentication error is detected, the call to HttpSendRequeststill succeeds. If corrective action is not taken the Internet server will return an error message that will be read by InternetReadFile. Authentication with InternetSetOptionAuthentication with InternetErrorDlg will display a dialog prompting for a username and password. In many situations, your application may already know the username and password to use and therefore should not prompt the user. In this situation, HttpQueryInfo is used to determine if the HTTP headers sent from the server contain authentication error information, and InternetSetOption sets the username and password for the request (Listing 8.4). Listing 8.4 Correcting authentication errors with InternetSetOptionDWORD dwStatus, dwStatusSize; dwStatusSize = sizeof(DWORD); if(!HttpQueryInfo(hHttpRequest, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE, &dwStatus, &dwStatusSize, NULL)) { cout _T("Could not query info") GetLastError(); } // Server Authentication Required if(dwStatus == HTTP_STATUS_DENIED) { // Set strUsername and strPassword InternetSetOption(hHttpRequest, INTERNET_OPTION_USERNAME, szUser, wcslen(szUser) + 1); InternetSetOption(hHttpRequest, INTERNET_OPTION_PASSWORD, szPassword, wcslen(szUser) + 1); } HttpQueryInfo is passed the following flags:
A pointer to the DWORD dwStatus is passed, and this variable will contain the status number on return. Notice that dwStatusSize is initialized with the size of a DWORD. The variable dwStatus will contain the value HTTP_STATUS_DENIED (which is the value 401) if a server authentication error occurred. HttpQueryInfo can be used to return all sorts of HTTP header information such as the length of the content to be returned (HTTP_QUERY_CONTENT_LENGTH) or its language (HTTP_QUERY_CONTENT_LANGUAGE), date when the content is deemed to have expired (HTTP_QUERY_EXPIRES), or the host and port number of the server (HTTP_QUERY_HOST).
The function InternetSetOption is used to set the username and password into the HTTP headers for the request (Table 8.11).
The function can be used to set other options, such as the following:
If you do not have access to a secure Internet site using NTLM, try connecting to http://www.softwarepaths.com/WinCEProgramming/Secure/Default.htm. This resource can be accessed with the user name "wince" and password "device."
|