ASP.NET: Using ECO III to Build Maintainable Applications with Authentication and Authorization in Delphi for .NET
ASP.NET comes with support to implement authentication and authorization out-of-the-box. You simply include the namespace System.Web.Security in your application and all the classes and methods you need are available. However, administration is not very comfortable using the standard classes. In this article I will show you how you can still use the classes provided in the framework and also bring ECO into play to make it much more comfortable to maintain your application and user credentials. It will give you maximum flexibility. You will be able to create user accounts, create groups and, finally, create content that may be restricted to any of those.
Basics
Before I start to explain the scope of our web application, I will juxtapose the terms authentication and authorization. Both terms are dependent on each other and have a fixed order. Authentication has to precede authorization. It is the process of discovering and verifying the identity of a user. This is normally done using a login that uniquely identifies the user in association with a password only known to him or her. Authorization is the second step that can only follow authentication. The user’s identity is being used to determine if he or she is allowed to access a certain resource of the application.
| Authentication |
process of discovering and validating the user’s identity |
| Authorization |
user’s identity is being used to determine which resources s/he has access to |
Table 1: Authentication and Authorization
Thinking of eBay, for example, you login to the system with your eBay name and also deliver a password to identify yourself to the system. This confirms to eBay that it is really you who is using the system and gives you access to your auctions etc. You are only authorized to change options of your auctions and your sales. It is impossible for you to change any settings that belong to other eBay users. In order to authenticate a user you need a list of all users that are allowed to use or access the application. In addition to that you also need to know what a certain user is allowed to access. You will find many examples on the internet that use databases for this. The .NET framework also offers the simple possibility of adding user-specific information to the web.config-file, which is easy to do, but almost impossible to administrate, because editing xml-documents manually can be a tedious task and is very error-prone. It is a fact that you can even put encrypted passwords into the web.config file, but this makes it even more difficult to add or edit user information to the document. I have also seen many examples that put the user credentials into the code, which would require a recompile whenever you want to add users or change their credentials. This approach is unacceptable to me as user administration and implementation of an application are two very separate tasks in my opinion. We, however, will look at a completely different method in this article. We will use ECO as our repository for user credentials. ECO will also be used to clarify if a user might be given access to a particular resource or not.
Be aware that this article requires basic knowledge about UML and ECO. I had a look at Bob Swart’s internet site and it contains some basic articles to get started with ECO. This very magazine also had some articles that should help you to get started with ECO in no time.
You will never build another web application without ECO ever again, as it will take away a significant amount of your development time!
Authentication in ASP.NET
Cookies and Configuration Files
This article will not explain all the possibilities to deal with authentication in ASP.NET in detail. I want to mention, however, that authentication requires the usage of cookies. There is no way around them. It is a common misconception that one can use other means instead of cookies. That is wrong. ASP.NET in .NET 1.1 requires cookies. Furthermore, you will have to include some code in every web page to check if the user has been authenticated successfully. There are means to put this into the web.config-file, but I consider it very bad design as I think an application should be understandable completely by looking at the source code. Considering that the complete application logic changed due to authentication and authorization parameters being set in a configuration file, would make it very difficult to understand the source code and will definitely lead to bugs when extending or simply modifying the application. Thus, I propose never to put authentication and authorization information into the web.config-file.
Using the web.config-file to specify authentication and authorization details is done quickly, but makes it harder to understand and maintain the source code of an application
Exemplary Authentication Session
It is important to understand how the process of authentication is supposed to work. First, there is the client and the server side. The server holds the credentials of all the users. A user is being redirected to a so-called login page whenever he/she tries to access a page that requires him/her to be authenticated already. This page enables him/her to enter the credentials, a login and password in most cases. When the user confirms the input, the values entered are being sent to the server and validated. There are two possible outcomes:
- The user credentials can be validated by the server and the authentication process is successful. The server immediately generates a so-called authentication cookie for the client, which is a flag on the client-side for a successful authentication. In addition to this, the client will also be redirected to the page the user tried to access originally, if his credentials allow him to access the page. Otherwise, the user will still be authenticated, but will have to be redirected to another page which he/she is authorized to access. Note, that it is your responsibility as a developer to implement all these redirects.
- The user credentials cannot be validated. The user is being redirected to the login page again and the authentication can be repeated. There is no cookie being generated.
The .NET framework gives you simple properties on your page which you can check if and which user has been authenticated. Thus, implementation is fairly easy as you will see later on when designing the login page.
Scope of the Application
We cannot describe how to build a complete web application in this article. It would take up too many pages. I can, however, deliver the essential building blocks to you. With these you will be able to create a complete web site of your own, which supports authentication and authorization with ECO support. You cannot only extend the pages, but also the ECO models to improve the usability and offerings on your site. In the next issue of this magazine, I will fine-tune the logic even more by using ECO State Machines, which are a new feature of ECO III.
Creating the Package Library
I decided to create a package that will contain the model, separately of the application. This has one huge advantage: the model is separate from the application and therefore you can also write client Winforms applications, for example, that you use to maintain your site. From my practical experience one can design a Winforms form much quicker than a ASP.NET page. This might be different in your case though.
Let us start by creating a new Delphi .NET model library. Borland calls this an “ECO Package in Package”, as we have packages in Delphi instead of libraries. The term is chosen poorly for the fact that you can have as many ECO packages as you want in such a package. You can create an ECO Package in Package using “File / New... / Other...” looking in the Delphi for .NET category. You will have to name and choose a location for your project right away. I named it “ACLModel”. Looking at the model view and expanding the top node, you can see that Delphi already created one ECO Package named “Package_1” for you. Rename this package by right-clicking it and selecting “Rename...” to “UserPkg”.
User Model
We will now design the classes that are associated with a person accessing your web site. A person will be either a user or an administrator in our design. They have a name, a login and a password. The latter two will have to be supplied for authentication. Our model should offer the ability to encrypt passwords and should also be able to validate a password.

Fig. 1: UserPkg; every user in our application is derived from Person and is either a User or an Admin.
Figure 1 shows the complete model. There are three classes: “Admin” and “User” inherit from “Person”. The class “Person” contains all the properties and methods right now. The properties are self-explanatory except the one named “/NameFull”. The “/” tells you that it is a derived attribute. You create those either by setting the “Derived” property in the object inspector to “True” or by prefixing your property name with a “/”. You will then have to define an OCL expression that yields the value of this property. Otherwise, ECO will create a function inside the code being generated from the model that you will have to implement. Complex operations should be implemented this way. “NameFull” is very simply the first name and the last name of the person. Thus, we can use the OCL expression “nameLast + ‘, ‘ + nameFirst” and no Delphi code is necessary. This “derived attribute” cannot be set, i.e. you cannot assign a value to it and expect “nameFirst” and “nameLast” being set accordingly. Though ECO has this functionality, it is not covered in this article. “User” and “Admin” will get operations at a later time to make the distinction between them meaningful. “Person” has two operations named “isCorrectPasswd” and “setPasswd”. These will become methods in the generated code. Their footprint and source can be seen in listings 1 and 2.
function Person.isCorrectPasswd(APasswd: string):
Boolean;
var
LEncryptedPw: String;
begin
LEncryptedPw :=
System.Web.Security.FormsAuthentication.
HashPasswordForStoringInConfigFile(
APasswd, 'SHA1');
Result := ( LEncryptedPw = self.passwd );
end;
Listing 1: Operation Person.isCorrectPasswd
The function “isCorrectPasswd” takes a password in clear text, encrypts it and compares it to the password of the person. During run-time we will first search the appropriate person using the “login” and can compare the password then. To encrypt the password we use a method that is provided by the .NET framework. It is also interesting that we will only store encrypted passwords, thus we need to encrypt any password a user describes to determine if it is the same. There is only the disadvantage that if a user forgets his or her password that you cannot recover it.
procedure Person.setPasswd(AClearPasswd: string);
begin
self.passwd :=
System.Web.Security.FormsAuthentication.
HashPasswordForStoringInConfigFile(AClearPasswd,
'SHA1');
end;
Listing 2: Operation Person.setPasswd
The function “setPasswd” encrypts a string and assigns it to the attribute “passwd”. This is all we will have to implement in this model.
We will now create a second ECO Package in our package. For that, right-click the top node in the model view, which has the name of your project, and choose “Add / ECO Package”. Be certain to create the package on the right level. It has to appear on the same level as the “UserPkg”. Name it “GroupPkg”.
Groups
Figure 3 shows the complete “GroupPkg” model. But what is this? “Person” – didn’t we design that class already? Yes, we did. And that is the nice thing about using packages. We are associating the class “Group”, which only has a name, to “Person”. Thus, we also implicitly link groups with users and administrators. You can include so-called shortcut classes by right-clicking the modeling surface and choosing “Add / Shortcuts...” (figure 2).

Fig. 2: Adding shortcuts in a Together model
Do not get distracted by the name of the package Delphi displays in the caption of the window, I have not figured out that naming convention either. Figure 5 shows the dialog that you can use to select the classes you want to import into your model. Expand the “UserPkg” node and double-click “Person”. Close the dialog by confirming with “OK” and you should get a class named “Person” in your model. In case you import multiple classes that are associated with each other you can even see those associations. The model for the groups needs an association between “Person” and “Group”. Thus, we will be able to make a user or an administrator the member of a group. Also take note of the fact that a person can be included in more than one group.

Fig. 3: GroupPkg: every Person can be a member of one or more groups. Note, that a User or an Admin inherit this association and thus can also be members.
Content
The final ECO package we will design is called “ContentPkg” (figure 4). It models the actual downloadable content on your site. Groups and persons can access content. It is important to understand that the model does not require a person to be member of a group for being allowed to download content. The model also has an association between “Person” and “Content”. I included two sample classes in the model: “Document” and “LicenseData”. I chose two completely different kinds of data on purpose. A document has a number of pages, whereas a license expires at some point. However, both have binary data and a title, which is modeled in the base class “Content”. “Content” can be made abstract if you do not want “general” content on your site. The package contains shortcuts from the packages “GroupPkg” and “UserPkg” and includes the classes “Group” and “Person”. This way one can associate the groups and users with the content.

Fig. 4: ContentPkg: Content is anything downloadable in our example. This model contains documents and license data as an example. Observe the arrows in the bottom left corner of the classes which tell you that these classes reside in another package.
Finally, we need one association that leads us to all the content that is accessible for a person. There are two associations and the information of those will be made available by using one additional derived association. Just like you specify an OCL expression for a derived attribute, you can specify OCL to return objects that are supposed to be members of that association. In our case, we want all the content that is either linked through groups or directly from the person. Thus, we draw an association from “Person” to “Content” and specify as OCL expression for end 2: self.memberInGroups.GroupDownloads -> union(self.Downloads).
These are all the packages and models. For the remainder of this article I will refer to all the different packages we designed as “the model”, even if all the different packages include models themselves. Delphi 2006 generates the code automatically while designing a model. I have run into a lot of problems because of this which made me switch off the automatic code generation while designing and use manual invocation instead. You can generate the ECO source code manually by using the two buttons on top of the model view.

Fig. 5: selecting shortcut classes
Building the Application
There are plenty of examples how to build ASP.NET applications. This article will focus on the fact that a well-designed model can speed up the process significantly. Furthermore, I realize that I still included a lot of methods in the page classes which could also have been put into the models as operations.
Let us start by creating a new ASP.NET ECO application. You can find it in the Delphi for .NET category in the “File / New / Other …” dialog again. Pay attention that you do not click “ASP.NET application” by chance as it will miss the ECO templates that make a quick set up of the ECO features possible. I also propose using IIS as the web server to reproduce this example. You will end up with one source file for your ECO space, one so-called “persistence mapper provider”, an ECO space provider, one aspx page and several configuration files. Before you can set up the ECO features, you need to add the model package to the references. In order to do that, right-click the “References” node in the project manager and browse for the compiled model dll-file. You have to build your application afterwards. Remember that building is different from compiling!
Setting Up the ECO Space
An ECO space has to know which model or models to include. We need to refer to the packages that are inside of our separate package. First, you have to open your ECO space by opening the pas-file that has the name of your application plus “EcoSpace.pas” by default. In my case the file is called “ACLApplicationEcoSpace.pas”. Right-click in the design area and select “Select Packages”. A dialog similar to figure 6 will appear. Select the three packages we designed and move “Package_1” from the right side to the left side. This is the default package that is being created with every ASP.NET ECO application which we obviously do not need. After confirming this dialog with “OK”, you have to re-build the project.

Fig. 6: Selecting all the UML packages to be included in the ECO Space. The three available packages on the left have to be selected in order to use the model we designed separately.
Persistence
ASP.NET ECO applications do need persistence. There is no way to execute an ECO web application without a persistence mapper. A persistence mapper can be considered the bridge between a database connection and the ECO space. It makes it possible to read and write objects to data storage without actually having to deal with this fact as a developer. You simply need to configure the connection once and need to create and update your database schema using the persistence mapper during design time whenever you make changes to your model. Furthermore, you cannot use the XML persistence mapper as this persistence mapper does not support multiple users accessing it. You always have to consider that multiple users might be logged in to your application. In order to proceed, create a database in your favourite database server you can connect to using a BDPConnection, for example. Afterwards, set up the database persistence in the “EcoPersistenceMapperProvider.pas” file. There is no difference to a non-web application. Just remember not to drop the persistence components onto the ECO space. I do not want to give any more details on database persistence with ECO. There are many examples on the internet, for example Bob Swart’s blog example, which show you how to set up database persistence in detail. Do not forget to create the database schema after setting it up.
A persistence mapper can be considered the bridge between a database connection and the ECO space.
Enabling Authentication
ASP.NET calls the kind of authentication I want to use in this example “Forms Authentication”. You might have noticed the name already reading the namespaces in the code listings. To switch to this authentication mode you have to modify the web.config-file in your project.
Listing 3: Setting the authentication mode inside web.config
Looking at listing 3, you might figure it out by yourself to replace the “Windows” with “Forms” in order to switch to the correct mode.
Designing the Login Page
We finally get to something that the user of your website can use and see. This page is to be shown whenever a user tries to access restricted content and has not been authenticated yet. If you look at listing 4, you can see that I kept it very crude as I want to focus on the authentication process and not on web design. I simply dropped two text boxes and a button on an ECO ASP.NET page. You can create a page like that using “File / New / Other…” and choose “ECO ASP.NET page” in the “New ASP.NET Files” subcategory. The text boxes are to be used to enter the login and the password. The button is to be pressed when the values have been entered and the actual authentication is supposed to occur. The first thing you should look into is how to use validator components to make it mandatory for the user to enter values.
<%@ Page language="c#" Debug="true"
Codebehind="login.pas" AutoEventWireup="false"
Inherits="login.TLoginForm" %>
"-//W3C//DTD HTML 4.01 Transitional//EN">
Listing 4: Login.aspx.
Listing 5 shows the implementation of the click event of the button. First, we try to find the user or admin object that matches the login. I have to use the “Person” class, of course, in order to make it possible to authenticate users and administrators. If the object can be found, we have to compare the password the user entered with the password that has been assigned to the person. If they match, authentication is successful. Otherwise, we will simply give the user another chance to enter his or her credentials. I emphasize that we use the ASP.NET classes to deal with the authentication logic. ECO does not require us to learn anything differently in comparison to authentication with “normal” ASP.NET applications. We simply use ECO to manage our user credentials.
procedure TLoginForm.btLogin_Click(
sender: System.Object; e: System.EventArgs);
var
Llogin: String;
Luser: UserPkgUnit.User;
begin
Llogin := txtLogin.Text;
Luser := self.getUserForLogin( Llogin );
// if a person exists with that login...
if Assigned(LUser) then
begin
// check password
if LUser.isCorrectPasswd( txtPasswd.Text ) then
begin
System.Web.Security.FormsAuthentication.
RedirectFromLoginPage( LUser.login, False );
end;
end;
end;
// returns nil if login does not exist
function TLoginForm.getUserForLogin(ALogin:
String): UserPkgUnit.Person;
var
Locl: IOclService;
Lobj: IObject;
begin
// -- get IOCLService
Locl := EcoServiceHelper.GetOclService(fEcoSpace);
// -- find first user with login = ALogin
Lobj := Locl.Evaluate(
'Person.allInstances->select(login
=''' + Alogin + ''')->first') as IObject;
if Assigned( Lobj.AsObject ) then
Result := Lobj.AsObject as UserPkgUnit.Person
else
Result := nil;
end;
Listing 5: Click event of the login-button and helper method.
A Page to Create Users
procedure TCreateUserPage.btCreate_Click(
sender: System.Object; e: System.EventArgs);
var
LUser : UserPkgUnit.User;
begin
if self.IsValid then
begin
LUser := UserPkgUnit.User.Create(EcoSpace);
LUser.nameFirst := txtNameFirst.Text;
LUser.nameLast := txtNameLast.Text;
LUser.login := txtLogin.Text;
LUser.setPasswd(txtPasswd.Text);
UpdateDatabase; // do not forget to
// apply changes!
lbStatus.Text := 'added: ' + LUser.nameFull;
end
else
begin
lbStatus.Text := 'please correct mistakes.';
end;
end;
Listing 6: Creating a new user.
Adding users to your web site is rather easy as you simply need to create an instance of the “User” class and assign the necessary values. I just would like to emphasize that you cannot assign as value to the attribute “passwd” directly as it has to be encrypted. For that we added an operation to the model, as you might remember. Thus, we simply call this method with the password in clear text and it will be encrypted. Also, always remember to call “UpdateDatabase” after making changes to an ECO space in web applications as the ECO space might be closed when the page is unloaded and you will lose your changes. The aspx page also contains validator components that make sure that only users with login and password can be added. I left out the check if the login you are trying to add is already being used.
Web Autoforms to Maintain Groups and Contents
ECO III comes with a new ASP.NET page template that allows you not only to view the objects that are currently in your ECO space, but it also allows you to create them and add them to associations. Simply use “File / New / Other…” and choose “ECO ASP.NET Auto Form” from the category named “New ASP.NET files”. You will end up with a page that contains a simple place holder. However, during run-time this page will allow you anything you need in order to build up your ECO space with objects. The only thing you cannot create this way are the user objects as they need an encrypted password and thus we designed a page for that.
A User-aware Download Page
I will close this article by showing you how to list all content that is accessible by a person that has been authenticated. Be aware that you have to check in the Page_Load-event if the user has been authenticated or not. Furthermore, I used a global object named “FPerson” that holds a reference to the person the download list is supposed to be created for. How do we get a reference to a person from one page to another? Using parameters is the answer. This parameter has to identify an object in the ECO space uniquely. To generate such an ID, we can use the utility method that is included in the template called “IdForObject”. Remember to call the method with an IObject. If you e.g. want to generate an ID for a object of the User-class, you would have to call “IdForObject( aPerson.AsIObject() )” to get the correct type. I refer to this as stepping from the “.NET World” into the “ECO World”.
The Page_Load-event can read such an ID and use the inverse method called “ObjectForId”. Again, we get an IObject and have to step back into the .NET world using the “AsObject”-property. I put that all in a separate method called “getPersonFromId”. The method “listContentForPerson” simply writes HTML into the Response with information on all the content that the person is allowed to access. For that the association “AllDownloads” is being used. You see how helpful derived associations are. If we had not created that additional association we would have needed two loops: one to get all the content the user is allowed to access directly and another to list the content that he has the right to use, because he or she is member of a certain group.
procedure TDownloadPage.Page_Load(
sender: System.Object; e: System.EventArgs);
var
Id: string;
begin
// check if user is authenticated.
// Response is only generated if
// user is authenticated.
if Page.User.Identity.IsAuthenticated then
begin
EcoSpace.Active := True;
// get parameter named RootId which
// contains an id which has been
// generated e.g. with
// self.IdForObject( anIObject )
Id := Request.Params['RootId'];
getPersonFromId(Id);
listContentForPerson;
end;
end;
procedure TDownloadPage.listContentForPerson;
var
Lcontent: Content;
i: Integer;
begin
// -- generate simple list of all
// available content
Response.Write('
');
for i := 0 to
FPerson.AllDownloads.Count - 1 do
begin
Lcontent := FPerson.AllDownloads[i];
Response.Write(
System.String.Format('- {0}
',
Lcontent.title));
end;
Response.Write('
');
Response.Close;
end;
procedure TDownloadPage.getPersonFromId
(Id: string);
var
Lobj: System.Object;
begin
// get Person matching the Id
Lobj := (ObjectForId(Id)).AsObject;
if Assigned(Lobj) then
FPerson := Lobj as Person;
end;
Listing 7: Code for the download page that checks if the user is authenticated and only lists content that can be accessed.
Conclusion
This article did not only show how to implement authentication and authorization with ASP.NET using code, it also brought ECO into the mix. We have seen that a well-designed model takes a lot of typing away and thus saves us a lot of time. Needless to say that we only looked at the basic functionality of ECO here and we could improve the model even more, for example using State Machines, which have been introduced in the latest version of ECO. I admit that setting up the ECO space and the database connectivity might seem odd at first, but it definitely pays off in the end. You do not have to deal with database queries yourself, ECO handles the database part for you. You can concentrate on the structure of your classes.
I hope to bring more light into the aspects that we only looked at very briefly in this article in later issues of this magazine. I was not able to explain Autoforms or how you can access objects in your ECO space in detail. I had to leave performance aspects completely aside. I also could not clarify the role of the ECO space in regard to the ASP.NET page model as there are some key aspects one has to think of when building bigger applications. However, this article has shown to you what is possible with ECO and might have triggered your interest to mine the internet for more information.
Sources
De sources die bij dit artikel horen kunt u downloaden via Flick_EcoAcl_SRC.zip.