This article is for webmasters who wish to protect their premium content directories with usernames and password according to their own specific requirements that are not covered by other AuthentiX validation choices, presently:
AuthentiX protects your IIS website by cookie or by Basic Authentication. You can use either method in combination with a custom AuthentiX plug-in. This tutorial explains how to protect your IIS website by cookie or by Basic Authentication using AuthentiX and your own custom authentication component using the AuthentiX Extensibility SDK.
We'll see how to create a server component in Visual Basic and Visual C++, a kind of component that can be used from Active Server Pages, ISAPI extensions or filters. Then how to use such a component with AuthentiX. Explanations, tips, samples and downloadable source code are provided here and in the evaluation product download. Special considerations for components called from NT services such as IIS are described.
The same component can be used with WebQuota to take advantage of its enhanced capabilities such as
If you wish to move from Basic Authentication to cookie-based protection, please see this additional note here.
Another option is to create a component without validating username/password, for example to check visitor IP-addresses, compare against a large database of acceptable IP-addresses.
Or map requests to NT users based on both the username and requested URL, in order to leverage MTS and other NT security mechanisms for users that they don't want to give NT accounts.
The Extensibility SDK is popular with those who need to validate against
multiple datasources, with appropriate failovers between them.
Eg, validate by IP address, if that fails then validate against a text file, if that
fails then validate against a mainframe via DCOM.
Eg validate against an NT username/password account (perhaps by trying to access
an NT protected template file), if that fails then an ODBC database.
Since the component will be called from a service, there should be no interaction with the desktop. That means no MsgBoxes and no dialogs. Should you incorporate a function library that throws up dialogs on error conditions, the best that can happen is the thread it is running in will hang, tying up resources. The worst is a service crash. Instead, services and their support functions should send a message to the event log. A support routine is available EventLog that will help you do this.
Since the IIS and AuthentiX environment is multithreaded, the component should be thread-safe. If two threads try to access the same data at the same time, conflicts will occur and may result in a crash. In general avoid global variables. If global variables must be used protect their access using synchronization objects.
The best option is to use only local variables (in function scope). Each thread uses its own stack for local variables so they are quite safe.
Some customers have tried building COM components using .Net. It should be noted that
.Net languages are interpreted and thus do not have the performance advantages of
purely compiled code.
.Net has garbage collection that occurs at unpredictable intervals. This can cause
rather severe performance bottlenecks at random times.
Finally, rather than being completely loaded into memory when first called, .Net components
need to load assemblies in real time each time they are called.
Some have reported performance penalties of several orders of magnitude when switching from
compiled Basic or compiled C++ to .Net.
One customer noted a performance drop from 0.04 seconds to 12 seconds! (6/6/05)
With VB5 and VB6 you can create a COM (or ActiveX) component quite easily.
Visual Basic produces a file with a "dll" extension, Visual C creates
a file with an "ocx" extension. Each must be registered with the system
using regsvr32.exe. From the command line you would enter
regsvr32 component.dll
You'll need Windows NT/2000, IIS and VB6 installed on your system.
Fire up VB, and click on the ActiveX Dll:
then click "Open".
In the Project Window, right click on the project name, click on
properties, change the project name to "MyAuthVB"
and check the "Unattended Execution" check box.
Press OK.
Now click on the class name "Class1 (Class1)" then select the "(Name)" property in the Property Window. Change the name to "Auth".
With a Project Name of MyAuthVB and a class name of
Auth, the OLE short name or "ProgID" is
MyAuthVB.Auth
You'll need this ProgID later when we hook the component into AuthentiX.
If you wanted to use some methods in this component from ASP, then you would
use this ProgID in the call to CreateObject like so:
Set MyAuth = Server.CreateObject("MyAuthVB.Auth")
Now create the Method to be called. To make the function available externally, it must be declared as a "Public Function". Here is a sample for you to begin with:
' return 1 for success
' returns 3 if user not found
' returns 6 if user found and wrong password
' returns 9 if user found and expired
| Public Function Authenticate( |
verifyArg As Long, _
username As String, _ password As String, _ ipAddress As String, _ userAgent As String, _ referrer As String, _ scriptName As String, _ ReservedReturn As String, _ queryString As String, _ bstrReserved2 As String, _ longReserved1 As Long, _ longReserved2 As Long) _ As Integer |
If ("Brian" <> username) Then
Authenticate = 3 ' bad username
Exit Function
End If
If ("Young" <> password) Then
Authenticate = 6 ' bad password
Exit Function
End If
Authenticate = 1 ' success
Exit Function
End Function
Here it is in a text file for easy cut and paste.
Next compile the project into a dll. In the File Menu, select "Make MyAuthVB.dll". This will create the ActiveX dll file and register it on your system.
You can test the above Authenticate method from WSH or ASP as follows:
Set MyAuth = Server.CreateObject("MyAuthVB.Auth")
result = MyAuth.Authenticate(1, "Brian", "Young", _
Request.ServerVariables("REMOTE_ADDR"), _
Request.ServerVariables("HTTP_USER_AGENT"), _
Request.ServerVariables("HTTP_REFERER"), _
Request.ServerVariables("SCRIPT_NAME"), _
str1, str2, str3, l1, l2)
5/9/00: One user reported that when using a VB component like this, as well as using ASP pages, then IIS will have a problem when shutting down. His solution was to make the VB component out-of-process, using the VB menu Project-Properties, and setting the project type to an "ActiveX Exe" instead of "ActiveX DLL".
5/21/01: One user had a permissions problem debugging with VB.
"I fixed this problem, it was a permissions problem in DCOM. Adding the
following Registry entry's and giving "Everyone" access permissions on the VB
ASP Debugging entry in the dcomcnfg tool allows you to debug the component.
REGEDIT4
[HKEY_CLASSES_ROOT\CLSID\{70F214BA-94E2-4bdf-8F30-32CB4A905E4D}]
@="VB ASP Debugging"
[HKEY_CLASSES_ROOT\CLSID\{70F214BA-94E2-4bdf-8F30-32CB4A905E4D}\LocalServer32]
@="vb6.exe"
[HKEY_CLASSES_ROOT\AppID\vb6.exe]
"AppId"="{70F214BA-94E2-4bdf-8F30-32CB4A905E4D}"
If your COM component returns values other than the standard values, be sure the values are ABOVE 900. 900 and below are non-user return codes, and will always be converted to BAD_PASSWORD.
Now that we have created and tested the component, it is time to hook it into AuthentiX. If you are not concerned with creating a VC++ component you can skip the next section.
Go to setting up AuthentiX to use the Component
You'll need Windows NT/2000, IIS and VC6 installed on your system. Be sure to implement IsInvokeAllowed as described below.
Fire up Visual C, select File, New.
Click on MFC ActiveX Control Wizard,
and in the Project name field type "MyAuthC".
Click OK.
In the first step of the control wizard, choose the default settings.
Click Next.
In the second step of the control wizard, click on the Advanced
button, and check the Windowless Activation checkbox.
Click OK then click Finished. Click OK on the confirmation dialog.
You have now created a new COM component project in Visual C.
Now we need to create a new Method. Click on the View Menu, and select
Class Wizard (alternatively use the Ctrl-W shortcut key). Select
the Automation tab.
Now add a Method named Authenticate of return type "Short" with the following parameter list:
long FAR* verify
BSTR FAR* username
BSTR FAR* password
BSTR FAR* ipAddress
BSTR FAR* userAgent
BSTR FAR* referrer
BSTR FAR* scriptName
BSTR FAR* bstrUserString
BSTR FAR* bstrqueryString
BSTR FAR* bstrReserved2
long FAR* longReserved1
long FAR* longReserved2
(Remember if you don't want to do this by hand, there is a prepared sample to help you.)
Click OK, then click the "Edit Code" button to go straight to the source file.
Let's create the body of the function:
| short CMyAuthCCtrl::Authenticate( |
long FAR* verify,
BSTR FAR* username, BSTR FAR* password, BSTR FAR* ipAddress, BSTR FAR* userAgent, BSTR FAR* referrer, BSTR FAR* scriptName, BSTR FAR* bstrUserString, BSTR FAR* bstrqueryString, BSTR FAR* bstrReserved2, long FAR* longReserved1, long FAR* longReserved2) |
if (0 != uName.CompareNoCase("Brian"))
return 3; // bad username
if (0 != uPass.CompareNoCase("Young"))
return 6; // bad password
return 1;
}
Here it is in a text file for easy cut and paste.
If your COM component returns values other than the standard values, be sure the values are ABOVE 900. 900 and below are non-user return codes, and will always be converted to BAD_PASSWORD.
Important - miss this and it won't work!
Next, and very important is to add the function IsInvokeAllowed. If
you do not add this function, you will not be able to call
any methods in this control!
// absolutely essential and critical
BOOL CMyAuthCCtrl::IsInvokeAllowed(DISPID)
{
return TRUE;
}
Compile the project using the shortcut "Shift-F8".
You can test the above Authenticate method from WSH or ASP as follows:
Set MyAuth = Server.CreateObject("MYAUTHC.MyAuthCCtrl.1")
result = MyAuth.Authenticate(1, "Brian", "Young", _
Request.ServerVariables("REMOTE_ADDR"), _
Request.ServerVariables("HTTP_USER_AGENT"), _
Request.ServerVariables("REMOTE_ADDR"), _
Request.ServerVariables("HTTP_REFERER"), _
Request.ServerVariables("SCRIPT_NAME"), _
str1, str2, str3, l1, l2)
Now that we have created and tested the component, it is time to hook it into AuthentiX.
Two sample components are supplied with the installation of AuthentiX. AUTHCOM.AuthCOMCtrl.1 and AuthXVB1.Auth. The first is a VC++ sample, the second is a VB sample. Both come with source code and are located in the ByCOM installation sub-directory. Each are hard-coded for the user "Brian" with a password of "Young".
Click the Test button. The test will complete successfully.
Using the combo-box, select the alternate component AuthXVB1.Auth.
Note that the dispatch ID changes from 1 to 1610809344 (which is 0x60030000 in decimal). If you declare other methods in your COM component, you may have to adjust the Dispatch ID accordingly. The default values provided correspond to the default Dispatch ID in the server components built previously in this document. They will also match any new component you build according to the previous instructions.
To find alternate numbers, open the dll in oleview program that comes with visual studio. Then it will show the hexadecimal number for each class.
Click the Test button again. The test will complete successfully.
Now you are ready to test your custom COM component live. Type in the Prog ID of your component in the first text-field. If you created the VB component above type in "MyAuthVB.Auth" and select "VB Starts At" radio button. If you created the VC++ component above type in "MYAUTHC.MyAuthCCtrl.1" and select "C++ Starts At" radio button.
Click the Test button again. The test will complete successfully.
Click OK, OK, to save your changes for AuthentiX protection for that directory.
Using a browser and http, type in the URL of your protected directory. You'll be prompted for your username and password. Enter "Brian", "Young". You'll see your protected web pages - success!
Other topics to be covered include "Options" for advanced settings, and "Testing your COM component" where we provide a tool to assist with rapid prototyping and debugging of your component.
You need to stop and restart IIS (IIS Admin from the control-panel/Services) each and every time you make a change. Needless to say this considerably slows down the edit/compile/test cycle.
You could test the component each time from the AuthentiX/By-Com/Test button, however you still have to launch AuthentiX select the directory, fire the Test button, and stop AuthentiX. Although AuthentiX is easy to use and setup, this sequence of operations can become tedious. For your convenience a test container "ATestC" is supplied
Look in the ByCOM/ATestC directory. Specify ATestC.exe as the target debug executable in your development environment. This lightweight application will save you time in your development. Remember however that ATestC doesn't multithread or have the login context of IIS.
We have described general requirements for the behaviour of a server component, and given detailed examples of how to create such a component in Visual Basic and Visual C++.
A test tool has been provided to speed the development cycle, and advanced AuthentiX COM options have been described in detail.
Leveraging the functionality of commercial grade software like AuthentiX with its Extensibility SDK provides immediate benefits and significantly compresses development time where your organisation needs to address specific authentication requirements.
Transparent use of the AuthentiX internal cache ensures the speediest website performance with the additional functionality you build. The upgrade path from AuthentiX to WebQuota provides a route to advanced capabilites such as limiting concurrent logins to help detect and prevent account abuse.
Copyright © 1998,1999 Kevin Flick
All rights reserved.
This document may not be reproduced or distributed in whole or in part
without prior written permission from the author.