Setting Up IIS
Let's jump in and get IIS set up for use with your application. On the taskbar, go to Start ě Programs ě Administrative Tools ě Internet Information Services (if Administrative Tools is not available on the Programs menu, you can access it through the Control Panel or by editing the properties of the taskbar and selecting Show Administrative Tools). This brings up the IIS console, as shown in Figure 2-1.
Figure 2-1: The Internet Information Services console
First you will create your own virtual directory. To do this, follow these steps:
Right-click the Default Web Site node located under the Web Sites folder. Select New ě Virtual Directory. Click past the first screen, enter the name Northwind as the alias for your virtual directory, and then click Next.
On this screen, you will select the physical directory to which the virtual directory points. Select Browse, browse to the C:\inetpub\wwwroot folder (if you used the default installation with IIS; otherwise, browse to wherever your wwwroot folder is located), click the Make New Folder button, and enter the name Northwind. Click OK, then Next, Next, and then Finish.
Back on the IIS console, you should now have a Northwind node under the Default Web Site node. If you click the node, you will notice that nothing is in the folder right now.
Next you will create the web.config file, which will contain your server application settings and remoting listeners.
Listeners "listen" for a request to be made on a certain channel and then route the request to the correct object for processing.
Creating the web.config File
The web.config file contains application-specific configuration information. An application can have multiple web.config files, which is common in ASP.NET applications (although an application can only have one web.config file per directory). This application will require only one web.config file. You have two ways to create a web.config file: manually or by creating an ASP.NET application within the IDE and letting Visual Studio .NET (VS .NET) create a template web.config file for you. Listing 2-1 shows the default web.config file that is created with a new ASP.NET application.
Listing 2-1: The Default web.config File
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.web> <compilation defaultLanguage="vb" debug="true" /> <customErrors mode="RemoteOnly" /> <authentication mode="Windows" /> <authorization> <allow users="*" /> </authorization> <trace enabled="false" requestLimit="10" pageOutput="false" traceMode="SortByTime" localOnly="true" /> <sessionState mode="InProc" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString="data source=127.0.0.1;user id=sa;password=" cookieless="false" timeout="20" /> <globalization requestEncoding="utf-8" responseEncoding="utf-8" /> </system.web> </configuration>
When .NET creates this file, it is fully commented with helpful tips on how to use each section. I have removed the comments for brevity, but you can view them by generating this file from a template.
See the sidebar "Using a Compilation Tag" for information on an undocumented issue with ASP.NET.
When you are building an application on your own computer, there are almost never any problems. But when you move into a team development environment and eventually into production, things get a little more difficult. I was working on a team a few months ago and we were using a development server to host our middle-tier components. It happened to be that the server was under my control, so it was running under my credentials. When other members of my team deployed the components to the IIS server, they kept getting an error message when they tried to run the application. The message they got was the following: "Access Denied to CommonDC." (CommonDC was the name of our data-centric component.)
After working with Microsoft for a few days, we determined that the cause of this error was a lack of permissions on the shadow folder. ASP.NET uses a shadow copy mechanism to hold a component in memory. This shadow copy lives in the folder C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\Temporary ASP.NET Files\[application name]. None of the other developers had permissions to this folder, but the permissions were granted to the ASP.NET worker process on the server. This works fine until you start using impersonation. When you are using impersonation (see the "Setting Up Authentication and Authorization" section), the process runs under the user account of the user logged on to the application. None of them had permissions to this folder, so they always got this error. I had to run the application first and then everything was fine.
To work around this, we had to give read/write access to this folder to all of the groups authorized to run this application. The compilation tag allows you to change the location where the shadow copies are created—but the user logging in still needs read/write permissions to this folder on the server. This may be considered a security issue, but I do not see it as much of one because they have to be authorized to get to the application anyway. This is never a problem when you are not using Windows authentication.
To create the web.config file manually, do the following:
Navigate to the Northwind folder you just created (this should be in C:\Inetpub\wwwroot\Northwind).
Add a new text document and rename it to web.config.
Enter the information in Listing 2-1 into this file.
To create the web.config file using VS .NET, do the following:
Start VS .NET.
Select File ě New Project.
In the Visual Basic Projects node, select the ASP.NET Web Application and click OK.
Note the folder that the project was created in (by default, if you do not change the application name, it will be in C:\Inetpub\wwwroot\WebApplication1), close VS .NET, and copy the web.config file from the ASP.NET application to the Northwind folder.
Now that you have a web.config file, you can examine and customize it for your needs. Let's start with the security settings in the configuration file.
Setting Up Authentication and Authorization
Before explaining the security settings in the web.config file, you need to understand two commonly misused words: authentication and authorization. Authentication is determining who has access to something, and authorization is determining what they have access to. You need to understand this important distinction when designing the security of your application.
Consider the following lines of code within the web.config file you just created:
<authentication mode="Windows" /> <authorization> <allow users="*" /> </authorization>
As you can see, the authentication mode is Windows by default.
Microsoft has made a major change with the .NET Framework. Whenever the Framework is setting the default for a property that has to do with security, it will always set it to the most restrictive setting possible. This is a good practice for developers in general.
There are three other possible authentication modes for an application: Forms, Passport, and None. Because this is an enterprise application, you will be using the Windows authentication option. In an enterprise, all users of your application will probably be authenticated against the same domain, so this is a viable choice. However, this is one of those choices you must make carefully. By choosing Windows authentication, external users will not be able to use the application unless all connections are made via a general domain account that the ASP.NET process can run under. Finally, you should consult a security professional because there are many more implications to this decision than can be discussed here.
Web applications use Forms authentication that can present a user interface to collect login information from a user. Because you are calling your objects over a remoting channel with no interface, this is not an option. You can use Passport authentication either within the enterprise or externally of the enterprise, so it is a good balanced choice. It does require that users have a Passport account, and the service cannot be incorporated for free.
For more information on using Passport authentication in your application, go to the following Web page: http://www.microsoft.com/netservices/passport/. You can also download the Passport Software Development Kit (SDK) at http://msdn.microsoft.com/downloads/default.asp?url=/downloads/sample.asp?url=/msdn-files/027/001/885/msdncompositedoc.xml&frame=true.
The authorization mode is set to an asterisk (*) by default. An asterisk, in conjunction with Windows authentication, means that any user who can be authenticated against the domain will be granted access to the application. For the purpose of building this application, this is OK; however, when building a real application, this is a bad idea. When you are developing an application, you should always develop it with the lowest level of authorization possible. How many times have you, as a developer, written an application that worked fine on your development systems but after you installed it you received a bunch of errors? A lot of this is because the users do not have Admin access on their systems, and therefore you should not have Admin access on yours. You should modify this because there are certain things you must have Admin access to do, but if you do develop under an Admin logon, you absolutely must be rigorous during testing to ensure that the testers do not test under an Admin account.
You can also use the authorization tag to allow Windows groups (or roles, as they are referred to in this file) and to deny both users and groups.
When you deny users or groups, you must place the deny tags before the allow tags. This is because .NET will stop checking for valid authentication the first time it hits an allow tag that permits the user access. Likewise, .NET will also stop checking for valid authentication the first time it hits a deny tag that rejects the user.
Add the following line below the closing authorization tag:
<identity impersonate="true" />
This line allows IIS to use the connected user's Windows information when connecting to other resources on the network.
If you do this in a tightly controlled environment, such as in a secure environment at work, you need to be cautious of one thing. If you deploy SQL Server on another machine, you must make sure the machine that hosts IIS is authorized for trusted delegation. If you do not, when you try to log on to SQL Server, you will receive an error that says "DOMAIN\ANONYMOUS_USER denied." There is a good reason for this. It can be a security problem if trusted delegation is on. You can find more information about this on the Microsoft Web site in the Knowledge Base Article Q325894.
Using the appSettings Section
Many times there are specific settings that you would like to keep in a configuration file so that you always have access to them and so that you can easily change them. The appSettings section of the web.config is precisely for this purpose. The app-Settings section can hold any values you want it to hold. This application will store only one setting in this file—the database connection string. The reason you want to store the connection string here is so that when your database location changes, as it does when moving from development to testing to production environments, you do not have to recompile your application.
Add the following tag below the opening configuration tag but above the opening system.web tag:
<appSettings> <add key="Northwind_DSN" value="Trusted_Connection=yes;server=localhost;Initial Catalog=Northwind" /> </appSettings>
This connection string assumes you are using the same machine that is hosting IIS to host SQL Server. If this is not the case, replace localhost with the correct server name. Because you are using Windows authentication in SQL Server, you do not need to include any user IDs or passwords in this string, so it is OK to place it in this file. However, if you plan to include this information because you cannot use Windows authentication, it is best practice to encrypt this information before you place it into this file.
Understanding Remoting Configuration Information
The system.runtime.remoting section shown in Listing 2-2 controls whether IIS will be able to find the remote object when your client code comes looking for it. System.Runtime.Remoting is the .NET namespace where the remoting classes are located. The channels tag says that you are going to use the HttpChannel as opposed to the TcpChannel.
Listing 2-2: The Remoting Configuration Information
<system.runtime.remoting> <application> <channels> <channel ref="http"/> </channels> <service> <wellknown mode="Singleton" type="NorthwindTraders.NorthwindDC.RegionDC, NorthwindDC" objectUri="RegionDC.rem"/> </service> </application> </system.runtime.remoting>
Note that you have not specified which type of formatter you will be using (binary or SOAP). This is because .NET will use whichever formatter it detects when the connection is made.
The service section describes all of the components whose services are being made available through IIS. The wellknown tag registers the object with IIS so it knows what to do when a request is made. In other words, IIS listens for calls made to these specific Uniform Resource Indicators (URIs). The mode can be either Singleton or SingleCall. The difference is that with a Singleton object, only one object is ever created; with SingleCall, one object is created for every client that makes calls to an object. Using SingleCall could spell disaster for a large application where scalability is the key to success. However, when using Singleton, you must make sure the object does not maintain state.
There is one area where you would want to have a Singleton object maintain state. Take, for instance, an application where three users are logged onto the application and one user makes a change to a database that the other users need to know about. With a Singleton object, you can call a delegate on the client (if that client is set up to receive a delegate), or you can have the clients routinely poll the remote object for changes. This is an excellent way to keep all clients up-to-date on the current state of the application.
The type tag contains the fully qualified object that you will be calling. In this case, the object is called Regions, and it is located in the NorthwindTraders.NorthwindDC namespace. The object type following the comma lists the assembly in which the class is located—in this case, NorthwindDC.
Do not include the assembly extension or you will receive an error when you try to call the remote object.
The final tag, objectUri, contains the value you will use to connect to this object. This will become clearer when you start building your local objects.
You have used the extension .rem for your objects' URI. This is a naming convention more than anything. When a remote object will be serialized as a SOAP message, the extension is .soap.
This wellknown tag is the one you will duplicate and change as you progress through building the application. Add the remoting section (shown in Listing 2-2) to the web.config just above the closing configuration tag.
Next, navigate to the C:\inetpub\wwwroot\northwind folder (or wherever you created the folder), and create a new folder called bin. Lastly, in the IIS console, right-click the Northwind node. Select Properties and then click the Directory Security tab. Click the Edit button located under the Anonymous Access Authentication and Control section. This brings up the dialog box shown in Figure 2-2. Clear the check box next to Anonymous Access, and make sure that only the Integrated Windows Authentication box is checked.
Figure 2-2: IIS Authentication Methods dialog box
Click OK and close all the open property windows. You are now done configuring IIS.