Checking User Account Status
The business requirements for this example aren't complex. I want to have a simple Web page that accepts a user ID, and then queries a predetermined NT or Active Directory domain to see if that user account is locked out or disabled. I want the results to be displayed on the bottom of the page, so that an administrator can quickly enter another user ID to check its status.
Designing the Page
I use Microsoft FrontPage to produce most of my Web page designs. It's easy, and with FrontPage 11, you don't get a lot of extraneous fancy HTML formatting, so it's easier to see what's going on.
Listing 24.1 shows the simple HTML form I cooked up in FrontPage.
Listing 24.1. Userprops.htm. This is a static HTML page that will be adapted to ASP later.
<html>
<head><title>Check User Account Status</title></head>
<body>
<p align="center"><b>Check User Account Status</b><i><br>
This page will work only for domain administrators
or account operators.</i></p>
<form method="POST" action="userprops.asp">
<p align="center">User ID:<br>
<input type="text" name="UserID" size="20"></p>
<p align="center"><input type="submit"
value="Submit" name="Submit"></p>
<hr noshade color="#000000">
</form>
<p align="center"><b>Status for<br>
<u>xx<br>
</u>yy</b></p>
</body>
</html>
If you open the page in FrontPage or even a Web browser, you'll notice that I've included some placeholder information. The "xx" and "yy" at the bottom of the page are where I want my script to insert the user ID and its account status. I find that including placeholder information like this helps me figure out exactly where in the HTML code my script needs to insert stuff. It also lets me apply formatting-such as boldfacing and underlining-by using FrontPage's excellent formatting tools, so that I don't have to worry about what the underlying HTML codes are.
TIP
Don't forget that you can load these listings from the CD accompanying this book. Try making your own customizations to Listing 24.1, perhaps changing colors or dressing up the formatting a bit. Leave the placeholder information alone, and you'll be able to easily incorporate the script code I'll show you later.
Writing Functions and Subroutines
There's not much code required for this example, but there's no reason not to write it as a function or subroutine. Why bother? Because it'll make the code easier to pull out and reuse in future scripts.
When I'm writing scripts for Web pages, I often like to start by writing a plain script in Notepad or another editor. This allows me to test the script code on its own, without fussing with the Web page stuff. After the script is working, I can incorporate it into the Web page easily enough.
Listing 24.2 shows the test script I wrote for this example. Notice that almost the entire script is a function; there's only one line of code outside the function, and that line of code simply calls the function to test it. By including all the code in a function (or sub), I can easily paste it into my Web page later.
Listing 24.2. TestUserAcct.vbs. This script checks the status of a particular user account.
MsgBox UserStatus("donjones")
Function UserStatus(sUser)
'bind to the provider
On Error Resume Next
Dim oUser
Set oUser = GetObject("WinNT://server1/" & _
sUser & ",user")
'user found?
If Err <> 0 Then
'no!
sMsg = "USER NOT FOUND"
Else
'user was found
'is this account disabled?
If oUser.AccountDisabled = "True" Then
sMsg = sMsg & " Disabled"
End If
'is this account locked?
If oUser.IsAccountLocked = "True" Then
sMsg = sMsg & " Locked Out"
End If
'neither?
If sMsg = "" Then
sMsg = "Normal"
End If
End If
'return result
UserStatus = sMsg
End Function
There are a couple of important things to notice about this script.
I've hard-coded a user name-donjones-to test with. That's outside of the main function, though, so I won't have to make a change when I move this script into the Web page. The domain is hard-coded within the function. In this case, it's "server1," which is actually the name of a particular domain controller. You'll want to change that to be a valid domain controller name or domain name in your environment.
Try using this script with several user accounts, including some that don't exist, some that are locked out, and some that are disabled. Ensure the script returns an appropriate response for each. Keep in mind that you can use the Windows Script Debugger and editors like VBSEdit or PrimalScript, making it easier to write and debug the bulk of your code.
Writing the Main Script
Now it's time to merge the script and the Web page. I'm going to use a slightly different technique than I've used in previous Web page examples. Check out Listing 24.3.
User Properties
This script prompts for a user ID, and then connects to a domain controller named Server1 to check on the status of the user ID. It can display a message if the user ID isn't found, if the ID is locked out and/or disabled, or if the account's status is normal.
Listing 24.3. UserProps.asp. The merged script and Web page.
<%
Function UserStatus(sUser)
'bind to the provider
On Error Resume Next
Dim oUser
Set oUser = GetObject("WinNT://server1/" & _
sUser & ",user")
'user found?
If Err <> 0 Then
'no!
sMsg = "USER NOT FOUND"
Else
'user was found
'is this account disabled?
If oUser.AccountDisabled = "True" Then
sMsg = sMsg & " Disabled"
End If
'is this account locked?
If oUser.IsAccountLocked = "True" Then
sMsg = sMsg & " Locked Out"
End If
'neither?
If sMsg = "" Then
sMsg = "Normal"
End If
End If
'return result
UserStatus = sMsg
End Function
%>
<html>
<head><title>Check User Account Status</title></head>
<body>
<p align="center"><b>Check User Account Status</b><i><br>
This page will work only for domain administrators
or account operators.</i></p>
<form method="POST" action="userprops.asp">
<p align="center">User ID:<br>
<input type="text" name="UserID" size="20"></p>
<p align="center"><input type="submit"
value="Submit" name="Submit"></p>
<hr noshade color="#000000">
</form>
<%
If Request("Submit") <> "" Then
%><p align="center"><b>Status for<br>
<u><% Response.Write Request("UserID") %><br>
</u><% Response.Write UserStatus(Request("UserID")) %></b></p>
<%
End If
%>
</body>
</html>
Notice that I plugged the actual function in at the start of the page. The main script code doesn't start until the middle of the actual HTML: I use an If…Then construct to see whether the form is being submitted. If it is, I display the second part of the HTML, replacing my placeholder "xx" and "yy" with Response.Write commands that display the appropriate information.
User Properties-Explained
I'll walk through what the script is doing. I start with the UserStatus function, which accepts a user ID as its only input.
<%
Function UserStatus(sUser)
Next, I bind to the WinNT ADSI provider. Remember, this allows the script to work with older NT domains as well as Active Directory domains. I plug the name of the user ID in the sUser variable. Note that you'll need to change server1 to either a domain controller or a domain that exists in your environment.
'bind to the provider
On Error Resume Next
Dim oUser
Set oUser = GetObject("WinNT://server1/" & _
sUser & ",user")
Did you notice the On Error Resume Next? If the user ID provided doesn't exist, ADSI won't be able to bind to it, and will return an error. I've told VBScript to ignore the error and resume executing code. In the next line of code, I check to see if the special Err object has a value of zero. If it does, no error occurred; if it's not zero, an error occurred and I can set an output message to indicate that the user wasn't found.
'user found?
If Err <> 0 Then
'no!
sMsg = "USER NOT FOUND"
Else
Now that the user was found, I can check its AccountDisabled and IsAccountLocked properties, which are set by the WinNT provider. If either is true, I concatenate an appropriate message to sMsg. I concatenate so that both "Disabled" and "Locked Out" can appear in the same message, because an account can be both locked out and disabled.
'user was found
'is this account disabled?
If oUser.AccountDisabled = "True" Then
sMsg = sMsg & " Disabled"
End If
'is this account locked?
If oUser.IsAccountLocked = "True" Then
sMsg = sMsg & " Locked Out"
End If
If sMsg is still empty at this point, the account was neither locked out nor disabled, so I set sMsg to include a message indicating that the account is normal.
'neither?
If sMsg = "" Then
sMsg = "Normal"
End If
End If
Finally, the function returns sMsg as its output.
'return result
UserStatus = sMsg
End Function
That's all of the function code, and now the regular text of the Web page begins.
%>
<html>
<head><title>Check User Account Status</title></head>
<body>
<p align="center"><b>Check User Account Status</b><i><br>
This page will work only for domain administrators
or account operators.</i></p>
<form method="POST" action="userprops.asp">
<p align="center">User ID:<br>
<input type="text" name="UserID" size="20"></p>
<p align="center"><input type="submit"
value="Submit" name="Submit"></p>
<hr noshade color="#000000">
</form>
Here's where the main script picks up. I check to see if the submit button was pushed. If it wasn't, this entire block of code-down to </body>-is skipped. The practical effect of the If…Then construct, then, is to not display any of the ASP code's output HTML the first time this page is displayed.
<%
If Request("Submit") <> "" Then
Although the next few lines are a mix of static HTML and VBScript code, none of these lines display if the logical condition for the If…Then construct isn't true. If the form was submitted, this code will output the user ID entered into the form, as well as the results of the UserStatus() function.
%><p align="center"><b>Status for<br>
<u><% Response.Write Request("UserID") %><br>
</u><% Response.Write UserStatus(Request("UserID")) %></b></p>
Finally, I'll wrap up the If…Then construct with an End If statement, and finish the static HTML for the page.
<%
End If
%>
</body>
</html>
This is a straightforward page, and it should run as-is, after you've corrected "server1" to be a domain controller or domain name that exists on your network.
NOTE
You can also point this script to a particular server and use the script to check local user accounts.
Testing the Page
I didn't include any tricky bugs in this page, so it should work as-is. If you're getting errors, or if you're getting "USER NOT FOUND" responses when you shouldn't, check to ensure that your ADSI connection path is correct, including the server or domain name. Also, make sure that you're authenticating to the domain as a member of the Domain Admins or Account Operators groups, because only those groups have permission to query the information that the script is trying to retrieve.
If you're having other types of problems with the Web page, go back to your Notepad version of the script (see Listing 24.2), and get that working first. You should be able to run it on the Web server as an administrator. If that works, and the Web page still doesn't, here are some possible areas for troubleshooting.
IIS may not allow ASP pages. This can be especially true on IIS 6.0, which doesn't enable ASP by default. IIS may be configured to allow anonymous authentication. IIS won't check your domain credentials if anonymous users are allowed, so you'll need to disable anonymous access to force IIS to recognize you as an administrator. ADSI might not be installed. It's installed by default on Windows 2000 and later, so make sure you're running on at least that operating system.
Before this script will work, you need to make sure that you have your IIS environment set up correctly. For this chapter, I assume that you're placing your ASP pages in an IIS folder, such as C:\Inetpub\Wwwroot. I also assume that you've configured the Web site to disallow anonymous authentication and to allow only Windows Integrated authentication. This configuration will ensure that only authorized users have access to the page. If unauthorized users gain access to the page, they still won't be able to use it, but they will receive an error message that might be confusing. Better to keep them out of areas where they don't belong! |
|