Authentication


Authentication can be useful on the Internet (for protecting access to a site or, more commonly, for protecting access to areas of a site), but it s even more popular on an intranet, where access is often managed with fine-grained control.

ATL Server supports NTLM authentication and Basic Authentication. NTLM authentication is a secure authentication mechanism that uses Windows security to authenticate the user . It s useful when you know that users of the site will be using Windows to access the site. You can usually determine this for intranet applications, but it s not always as feasible for Internet applications (although if you re providing a section of your site to vendors or partners , it can be very useful). The CNTLMAuthObject class in atlhttp.h is where NTLM authentication is implemented. CNTLMAuthObject is derived from CAtlBaseAuthObject , which provides the general requirements for any authentication function (initialization and authentication).

Basic Authentication is a simpler authentication mechanism that takes a username/password combination to control access to the site. This authentication mechanism provides no encryption by default, which is why it s important to ensure that you re using an encryption mechanism such as HTTPS when you use this protocol. Basic Authentication can be very useful for controlling access to parts of a Web site or customizing a site for a particular user. CBasicAuthObject in atlhttp.h is where Basic Authentication is implemented. The application must implement an IAuthInfo interface (and pass it to the CBasicAuthObject ) in order for the call to succeed. This class also derives from CAtlBaseAuthObject .

You ll note that if either of these functions fail, the application will return a 401 error with an indicator that authorization is required. This is generally a sound policy, as it limits the information that anyone can glean from the failure. In particular, the user has no information as to what authentication mechanism is being used and why it failed (information that may help a potential hacker).

NTLM Authentication

Using NTLM on the server side is usually done in one of two ways. One option is to use the IIS administration tool to set the permissions on a given vroot. IIS will then be responsible for receiving and interpreting authentication information. This does mean that a user either has access to the entire application or doesn t have access to the entire application. The other option is to do the authentication in your actual application. The code for this is fairly simple and looks something like Listing 26-1.

Listing 26.1: Confirming That NTLM Authentication Is Being Used
start example
 CString str;  CString ntlm = "NTLM";  BOOL b = m_HttpRequest.GetAuthenticationType(str);  if (b == FALSE)  {    return HTTP_UNAUTHORIZED;  }  if (str == ntlm)  {    // Set the content type    m_HttpResponse.SetContentType("text/html");    return HTTP_SUCCESS;  }  return HTTP_UNAUTHORIZED; 
end example
 

This code should be simple to follow.

Caution  

You ll need to disable anonymous access on the vroot in order to have the code in Listing 26-1 work correctly.

The other side of NTLM authentication is authenticating from the client. Internet Explorer automatically pops up an NTLM authentication credentials window, but what about a custom client application?

This is where CNTLMAuthObject comes into play. You can either use the default setting (log in as the current user) or implement IAuthInfo in order to authenticate in a different manner (log in as a different user or prompt for credentials):

 int main(void)  {    CoInitialize(NULL);    NTLMAuthService::CNTLMAuthService svc;  #ifdef SECURE    CNTLMAuthObject auth;    svc.m_socket.AddAuthObj("NTLM", &auth);  #endif    CComBSTR bstrIn, bstrOut;    bstrIn = "World!";    svc.HelloWorld(bstrIn, &bstrOut);    printf("%S", bstrOut);    return 0;  } 

With this client you re using an ifdef block to contain the code that sends the authentication information. This way, you can easily check that the call only succeeds when you have your authentication information included.

If you look at the code for this chapter (you can download the code for this book from the Downloads section of the Apress Web site [http://www.apress.com]), you can see that we ve used a similar #define around the Web service server, so that you can easily check that it s authenticating against NTLM. Notice that if you disable the code on the server, the client will never authenticate correctly (and thus the call will always fail).

Basic Authentication

Basic Authentication follows exactly the same pattern as NTLM authentication. You can use either IIS or Internet Explorer to handle authentication on the server side and the client side, respectively, or you can use the classes provided to implement the authentication manually.

Caution  

One warning about Basic Authentication is that it transmits the user information (username and password) as plain text. This means that you must use an encryption scheme if you want to use this method of authentication.

In general, the same principles apply when you want IIS to handle authentication as when you want to do it yourself.

Caution  

When we talk about do-it-yourself security, we re really referring to using the supplied APIs that handle the security for you. For the vast majority of developers, implementing a custom security system isn t recommended.

In the next sections you ll look at code snippets that show how the server and client code looks.

Server-Side Authentication Code

You don t have to verify if the user is using Basic Authentication in your code ”you can always have IIS do the verification for you. If you support multiple types of authentication (e.g., Basic Authentication or NTLM authentication), you might want to treat the two types of users differently, and in these cases using code to verify the authentication type may be useful, as shown in Listing 26-2.

Listing 26.2: Verifying the Use of Basic Authentication
start example
 [    request_handler(name="Default", sdl="GenbasicauthWSDL"),    soap_handler(      name="basicauthService",      namespace="urn:basicauthService",      protocol="soap"    )  ]  class CbasicauthService :  public IbasicauthService  {  private:    BOOL Auth;    CHttpRequest m_HttpRequest;  public:    // override HandleRequest    HTTP_CODE HandleRequest(AtlServerRequest *pRequestInfo,         IServiceProvider * pProvider)    {      // We need to create an m_HttpRequest in order to Authenticate      HTTP_CODE hRet = m_HttpRequest.Initialize(pRequestInfo->pServerContext, 0, 0);      CString str;      CString type = "Basic";      BOOL b = m_HttpRequest.GetAuthenticationType(str);      Auth = FALSE;      if ((b == TRUE) && (str == type))      {        Auth = TRUE;      }      return __super::HandleRequest(pRequestInfo, pProvider);    } 
end example
 

Client-Side Authentication Code

The client code is a little more complex than a normal Web service client, as you need to pass the authentication information yourself. In Listing 26-3, we ve put a note for where you should prompt the user for his or her username and password and copy them into your structure. Remember that this information will exist in plain text and will transmit in plain text, which is why an encryption system is critical.

Listing 26.3: The Client Side of Basic Authentication
start example
 class BasicAuth : public IAuthInfo  {    HRESULT GetUsername(LPTSTR lpBuffer, DWORD *pdwBuffSize)    {      if (*pdwBuffSize < 10)      {        *pdwBuffSize = 10;        return E_OUTOFMEMORY;      }      GET USERNAME AND COPY USERNAME INTO lpBuffer      *pdwBuffSize = strlen(lpBuffer);      return S_OK;    }  HRESULT GetPassword(LPTSTR szPwd, DWORD *pdwBuffSize)    {      if (*pdwBuffSize < 10)      {        *pdwBuffSize = 10;        return E_OUTOFMEMORY;      }      GET PASSWORD AND COPY INTO szPwd      *pdwBuffSize = strlen(szPwd);      return S_OK;    }    HRESULT GetDomain(LPTSTR lpBuffer, DWORD *pdwBuffSize)    {      if (*pdwBuffSize < 10)      {        *pdwBuffSize = 10;        return E_OUTOFMEMORY;      }      _tcscpy(lpBuffer,"PRANISHK-V1 
 class BasicAuth : public IAuthInfo { HRESULT GetUsername(LPTSTR lpBuffer, DWORD *pdwBuffSize) { if (*pdwBuffSize < 10) { *pdwBuffSize = 10; return E_OUTOFMEMORY; } GET USERNAME AND COPY USERNAME INTO lpBuffer *pdwBuffSize = strlen(lpBuffer); return S_OK; } HRESULT GetPassword(LPTSTR szPwd, DWORD *pdwBuffSize) { if (*pdwBuffSize < 10) { *pdwBuffSize = 10; return E_OUTOFMEMORY; } GET PASSWORD AND COPY INTO szPwd *pdwBuffSize = strlen(szPwd); return S_OK; } HRESULT GetDomain(LPTSTR lpBuffer, DWORD *pdwBuffSize) { if (*pdwBuffSize < 10) { *pdwBuffSize = 10; return E_OUTOFMEMORY; } _tcscpy(lpBuffer,"PRANISHK-V1\0"); *pdwBuffSize = strlen(lpBuffer); return S_OK; } }; int main(void) { CoInitialize(NULL); basicauthService::CbasicauthService svc; BasicAuth ba; CBasicAuthObject auth(&ba); svc.m_socket.AddAuthObj("BASIC", &auth); CComBSTR bstrIn, bstrOut; bstrIn = "World!"; svc.HelloWorld(bstrIn, &bstrOut); printf("%S", bstrOut); return 0; } 
"); *pdwBuffSize = strlen(lpBuffer); return S_OK; } }; int main(void) { CoInitialize(NULL); basicauthService::CbasicauthService svc; BasicAuth ba; CBasicAuthObject auth(&ba); svc.m_socket.AddAuthObj("BASIC", &auth); CComBSTR bstrIn, bstrOut; bstrIn = "World!"; svc.HelloWorld(bstrIn, &bstrOut); printf("%S", bstrOut); return 0; }
end example
 



ATL Server. High Performance C++ on. NET
Observing the User Experience: A Practitioners Guide to User Research
ISBN: B006Z372QQ
EAN: 2147483647
Year: 2002
Pages: 181

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net