Building a webstore with programmable security in .Net
This is part of a series of article I am writing on what is required to attempt the migration of Custom IBM “Domino” applications to a Microsoft Environment (.Net / SQL Server / Exchange ).
Some other posts for background work on this are :
Integrating Domino data with .Net
Building a "Domino" like data router in .Net
Another great feature of IBM Domino is that it has a web-store with programmable security built-in. This means that if I attach an Excel spreadsheet to a document in a notes database; then that spreadsheet automatically gets the security model wrapped around it that applies to the document it is attached to. As a “Domino” database is viewable from the web, it means that by simply attaching files to documents in a notes database you have created a secure web-store for those documents.
IBM Domino provides a security model that is extremely easy to programmatically manipulate. There are a couple of levels of over-arching security which aren’t really programmable, then there is
Database access
View access
Form Access
Document Access
Section Access
Most Domino developers implement data security at the Database Level and then refine that security programmatically at the document level. At the database level you use an Access Control List to specify who can access the database and specify what their maximum access level is (Manager,Designer, Editor,Author,Reader,Depositor) and which ACL Roles they belong to. This can be done on a per user or per group (or both).
At the document level the Domino Developer can add “Reader” and “Author” fields to documents containing the list of users, groups and/or ACL Roles. If a users is listed in a “Reader” field (maybe by group or ACL Role membership) then they can at least read a document, if the are in an “Author” field then they can “Edit” a document. (Access control is hierarchical, so if you are only a Reader at the Database level, then being in an “Author” field of a document still only makes you a Reader).
Changing access to a document and it’s attached files is therefore very easy. All you need to do is adjust a Reader Field and it effects who can view that document, and that also means any file attachment(s) on that document.
For instance, here is a computed formula that adjusts who can read the document based on the a field “DocStatus” which may be the current status of the document in the workflow.
@if(DocStatus=”Complete”; ”Joe Bloggs/Unit1/Company”;”[AdminSupport]”:”Sales”:”Joe Bloggs/Unit1/Company”);
This formula states that if the DocStatus field is “Complete” ( this may be a dropdown list for the user or a field set by some system process ) then only “Joe Bloggs” can read this document, otherwise anyone in the AdminSupport ACL Role, the Sales Group or Joe Bloggs can read the document.
This formula is obviously overly simple, but as the security model and data are exposed to the web via the Domino http stack, it means that in this 1 line of formula you have created a secure web-based workflow system. Any file attached to documents in this database are also contained inside the secure web-store so they too are part of the workflow. This simple example shows how quickly you can implement a secure web-based workflow system in IBM Domino.
Now how to replicate this functionality with .Net ? There have been rumours for years that Microsoft we going to release a product that had this sort of functionality “out-of-the-box”, but it has never materialised. So once again we need to code this.
If you want to allow someone access to an excel spreadsheet via the web using Microsoft products then you place it somewhere on and IIS server. If you want to restrict access you place some file level access around it. But what do you do if you want to restrict access to that spreadsheet based on where it is in a workflow? You could programmatically adjust the file system access I guess, but what if you have 100000+ records in a 20 stage workflow and 5000 users?
You could possibly use a SharePoint Server to store the files, but the access control seems to be nowhere near granular enough to do this, so I don’t think this is an option. Also I already need Exchange , IIS and SQL Server for other parts of the migration. Do I really want to add another server technology to this solution ??? Not if I can help it.
There are two components to this:
1) Determining the access a user has to a file based on some type of access control and business logic.
2) Storing the files so that they are within the programmable secure store.
Determining the Access a user has to a file based on access control and business logic.
IBM Domino provides a fully integrated security engine in the product. So there is no actual programming required to implement the security model. In .Net there are a number of ways to implement security. I use a SQL based .Net Role Provider. I am not going to go into detail about writing Role providers here as there are a number of good resources on the net, and how you implement them is determined by your application environment.
http://msdn2.microsoft.com/en-us/library/aa479032.aspx
http://weblogs.asp.net/scottgu/pages/Recipe_3A00_-Implementing-Role_2D00_Based-Security-with-ASP.NET-2.0-using-Windows-Authentication-and-SQL-Server.aspx
But to implement a web-store in .Net you will need to provide some form of usuable security provider so you can determine what the current users’ access level is to the data they are viewing.
Once you have implemented this then you should be able to write methods on your pages that follow similar logic to the code below.
protected bool CanUserPerformAction(string Action)
{
bool retval=false;
switch (Action)
{
case "Read":
//if user can access site then they can access this form retval = true;
break;
case "Edit":
if ((Roles.IsUserInRole("Administrator")) (Roles.IsUserInRole("Editor"))){
retval=true;
}
break;
case "Delete":
if (Roles.IsUserInRole("Administrator")) {
retval=true;
}
break;
case "Create":
if ((Roles.IsUserInRole("Administrator")) (Roles.IsUserInRole("Editor"))){
retval=true;
}
break;
}
return retval;
}
This method combines simple business logic ( the action trying to be performed ) and user acess to determine if the user can perform a certain action on the data. Obviously for complicated workflows this method would contain all of the business logic to determine if the current user could perform the requested action.
Storing the files so that they are within the programmable secure store.
If a file is to used inside an application then the access to that file must be controllable by that applications business logic. If you place a file on an IIS server in an area that is directly visible via http, then the control you have over the access to that file is limited. To create a fully-programmable webstore you really need to move the files outside the standard IIS space so there are not directly loadable via http from the file store. That way it is impossible for a user to load this file via http without first going through some security logic. You can either store the file on the file system (outside of IIS reach) or inside a database. For my own purposes the storing of the files inside SQL is the approach I have taken because this approach allows me to integrate with the .Net data router I have already built.
The following code is used to store files uploaded via an asp .net web form in an SQL Server database.
protected void SaveFiles(int Entryid)
{
System.Web.HttpFileCollection myfiles = System.Web.HttpContext.Current.Request.Files;
if (myfiles.Count != 0)
{
for (int iFile = 0; iFile < postedfile =" myfiles[iFile];" filename ="=" nfilelen =" postedFile.ContentLength;" myfiledata =" new" attds =" new" theatt =" AttDS." filenamearr =" postedFile.FileName.Split(@" filename =" FileNameArr[FileNameArr.GetUpperBound(0)];" inboxid =" Entryid;" contenttype =" postedFile.ContentType;" filedata =" myFileData;" attachnum =" iFile">
Once the files are in the SQL database then they are within the bounds of the application security model. The only way that the user can download/view the file is via a custom download page within the application. This page contains the security business logic (from above) to determine if a user can or cannot download/view the file. If they can then the following code is called to retrieve the file back from SQL and display to the user is as follows:
protected void DisplayFile(int Entryid){
AttachmentsDS AttDS = new AttachmentsDS();
//Attempt to retrive file from SQL via business object
AttDS = MyApp.DLC.AttachmentsDLC.GetAttachment(Entryid);
if (AttDS.Tables[0].Rows.Count == 0)
{
//there was no data returned so redirect.
Response.Redirect("~/ErrorPage?ErrNo=2392");
Response.End();
}
AttachmentsDS.AttachmentsRow dr = (AttachmentsDS. AttachmentsRow)AttDS.Tables[0].Rows[0];
Response.ContentType = dr.ContentType;
Response.AddHeader("Content-Disposition", "attachment; filename=\"" + dr.FileName + "\"");
Response.AddHeader("Content-length", dr.FileData.Length.ToString());
Response.OutputStream.Write(dr.FileData, 0, dr.FileData.Length);
}
Conclusion
Using a .Net Role Provider, some custom code and SQL server it is possible to create a secure programmable web-store for files. It is therefore possible to implement a web-based workflow system that contains attached files using this system. If this functionality is used along with the .Net data router then e-mails with attached files can automatically become part of a secure web-based workflow.
Again however this shows the amount of work required to implement something that is already built into the IBM Domino server. The creation of a SQL based role provider that suited my requirements actually took me about 3 weeks of research and coding. (This was somewhat due to the fact that I wanted the .Net SiteMap provider and the Role Provider to provide integrated security.)
In my next post ( when I get time to write it ) I will talk about implementing one of the last pieces of the system. A time scheduled and mail delivery notifier for .net to replace event driven and scheduled agents in IBM Domino.
0 Comments:
Post a Comment
<< Home