Http://www.codeproject.com/aspnet/formsroleauth.asp
Introduction
Forms authentication in ASP. net can be a powerful feature. with very little code and effort, you can have a simple authentication system that is platform-agnostic. if your needs are more complex, however, and require more efficient controls over assets, you need the flexibility of groups. windows Authentication gives you this flexibility, but it is not compatible with anything but Internet Explorer since it uses NTLM, Microsoft's proprietary authentication system. now you must choose how to manage your assets: provide multiple login pages/areas and force users to register for each, or assign groups to users and limit access to pages/areas to particle groups. obviusly, you must choose the latter.
Role-based security in Forms authentication is one thing Microsoft left out in this round. net, but they didn't leave you high-and-dry. the mechanisms are there, they're just not intuitive to code. this tutorial will cover the basics of Forms authentication, how to adapt it to make use of role-based security, and how to implement role-based security on your site with Single Sign-ons.
Prerequisites
This tutorial is all about role-based security with forms authentication, a detail that Microsoft left out. net for this round. this tutorial will use different techniques that are almost completely incompatible with the standard forms authentication, save the setup, which we'll cover shortly.
To follow along in this tutorial, you'll need to create a database, a Web application, several secured directories, and a few ASP. NET web forms (pages ).
Creating the database
we will create a simple database containing a flat table for this tutorial. using the
section of the Web. config file is not an option because no mechanisms for roles is supported. for the purposes of breses, the table we create will be very simple. you're welcome to expand the database to make use of relations (what I wocould do and actual do use on several sites) for roles. the implementation does start to get a little messy depending on how you do it, and the details are left up to you. this is merely a tutorial about developing role-based security.
SO, choose what database management system you want to use (DBMS ). for this tutorial, we'll choose the Microsoft Data Engine (MSDE) available with Visual Studio. net, Office XP developer, and several other products. we'll add one database, say Web
, and then add one table, say Users
. to the Users
table, we'll add three fields: username
, password
, and roles
. set the username
field to the primary key (since it'll be used for look-ups and needs to be unique ), and optionally create an index on the username
and password
fields together. if you're using table-creation SQL scripts, your script might look something like this:
CreateDatabase WebCreate TableUsers (usernameNvarchar(64)ConstraintUsers_pkPrimary Key, PasswordNvarchar(128), RolesNvarchar(64))Create IndexCredentialsOnUsers (username, password)
Feel free to add some credentials to your database, picking a few roles you think are good group names for your site, such as "Administrator", "manager", and "user ". for this tutorial, put them in comma-delimited format in the "Roles" field like the following, pipe-delimited (|) table:
Username | password | roles"Hstewart" | "codeproject" | "Administrator, user" "Joe" | "schmoe" | "user"
Take note to make the roles case-sensitive. Now let's move on to creating our pages necessary for role-based forms authentication.
Creating the login pages
If you haven't already done so, create a new web application, or attach to an existing web application, such as your web server's document root ,"/". for this tutorial, we'll assume the web application resides in "/", though the procedure for any web application is the same.
before we create any pages or setup our Web. config file, you must understand one thing: the login. aspx (or whatever you call your login page) must be public. if it isn't, your users will not be able to log-in, and cocould be stuck in an infinite loop of redirects, though I 've not tested this and don't care. so, this tutorial will assume that login. aspx is in "/", while we have two secured sub-directories, Users and administrators .
first, we must create a Forms authentication login system that supports roles. because Microsoft did not provide for this easily, we will have to take over the process of creating the authentication ticket ourselves! Don't worry, it's not as hard as it sounds. A few pieces of information are needed, and the cookie has to be stored under the right name-the name matching the configured name for Forms authentication in your root Web. config file. if these names don't match, Asp. net won't find the authentication ticket for the Web application and will force a redirect to the login page. for simplicity, we will put the Code directly into the ASP. net web form, which is easier to code for devhood and shoshould look something like the following:
<% @ Page Language = "C #" %> <% @ import namespace = "system. data "%> <% @ import namespace =" system. data. sqlclient "%> <HTML>
you'll notice above that we do one other thing with our passwords: we hash them. hashing is a one-way algorithm that makes a unique array of characters. even changing one letter from upper-case to lower-case in your password wocould generate a completely different hash. we'll store the passwords in the database as hashes, too, since this is safer. in a production environment, you 'd also want to consider having a question and response challenge that a user cocould use to reset the password. since a hash is one-way, you can't be able to retrieve the password. if a site is able to give your old password to you, I 'd consider steering clear of them unless you were prompted for a client SSL certificate along the way for encrypting your passphrase and decrypting it for later use, though it shower still be hashed.
Note: Without using HTTP over SSL (https), your password will still be sent in plain-text authentication ss the network. hashing the password on the server only keeps the Stored Password secured. for information about SSL and acquiring a site or domain certificate, seeHttp://www.versign.comOrHttp://www.thawte.com.
If you don't want to store hashed passwords in the database, change the line that readsFormsauthentication. hashpasswordforstoringinconfigfile (password. value,"MD5")
To justPassword. Value
.
next, we'll need to modify the global. asax file. if your web application doesn' t have one already, right-click on the web application, select "Add-> Add new item... -> global application class ". in either the global. asax or global. asax. CS (or global. asax. VB , if you're using VB. net), find the event handler called application_authenticaterequest
. make sure it imports/uses the system. security. principal
namespace and modify it like so:
protected void application_authenticaterequest (Object sender, eventargs e) { If (httpcontext. current. user! = null ) { If (httpcontext. current. user. identity. isauthenticated) { If (httpcontext. current. user. identity is formsidentity) {formsidentity id = (formsidentity) httpcontext. current. user. identity; formsauthenticationticket ticket = ID. ticket; // get the Stored User-data, in this case, our roles string userdata = ticket. userdata; string [] roles = userdata. split (','); httpcontext. current. user = New genericprincipal (ID, roles) ;}}
What's happening above is that since our principal (credentials-which are your username and roles) is not stored plainly as part of our cookie (nor shocould it, since a user cocould modify their list of Role-memberships), it needs to be generated for each request. theFormsauthenticationticket
Is actually encrypted as part of a cookie using your machine key (usually configured inMachine. config) AndFormsauthentication
Module decrypts the tick as part of the user's identity. If you search long and hard enough on MicrosoftMsdnWeb site, you'll find this documentation buried. We useUserdata
To obtain the list of roles and generate a new principal. once the principal is created, we add it to the current context for the user, which the processing page can use to retrieve credentials and role-memberships.
Securing directories with role-based forms authentication
To make the role-based authentication work for Forms authentication, make sure you haveWeb. configFile in your web application root. For the authentication setup, this participatesWeb. configFileMustBe in your web application's document root. You can override<Authorization/>
InWeb. configFiles for sub-directories.
To begin, make sure yourWeb. configFile has at least the following:
<Configuration> <system. web> <authenticationmode = "forms"> <forms name = "mywebapp. aspxauth "loginurl =" login. aspx "Protection =" all "Path ="/"/> </authentication> <authorization> <allow users =" * "/> </authorization> </system. web> </configuration>
The formsauthentication name (Mywebapp. aspxauth
) Abve it arbitrary, although the name there and the name inHttpcookie
We created to hold the hashedFormsauthenticationticket
Must match, for even though we are overriding the ticket creation, ASP. NET still handles the authorization automatically fromWeb. configFile.
To control authorization (access by a participant user or group), we can either 1) add some more elements toWeb. configFile from above, or 2) create a separateWeb. configFile in the directory to be secure. While, I prefer the second, I will show the first method:
The Web application always creates relative paths from the paths entered here (evenLogin. aspx), Using it's root directory as the starting point. to avoid confusion with that condition and to make directories more modular (being able to move them around und without changing a bunch of files), I choose to put a separateWeb. configFile in each secure sub-Directory, which is simply<Authorization/>
Section like so:
<Configuration> <system. Web> <authorization> <! -- Order and case are important below --> <allow roles = "Administrator"/> <deny users = "*"/> </authorization> </system. web> </configuration>
Notice, too, that the role (s) is/are case-sensitive. If you want to allow or deny access to more than one role, delimit them by commas.
That's it! Your site is setup for role-based security. If you use code-behind, compile your application first. Then try to access a secure directory, such/Administrators, And you'll get redirected to the login page. If login was successful, you're in, unless your role prohibits it, such as/AdministratorsArea. This is hard forLogin. aspxPage to determine, so I 'd recommend a session variable to store the login attempts and after so many times, return an explicit "Denied" statement. there is another way, however, which is discussed below.
Conditionally showing controls with role-based forms authentication
Sometimes it's better to show/hide content based on roles when you don't want to duplicate a bunch of pages for varous roles (user groups ). such examples wocould be a portal site, where free-and membership-based accounts exist and membership-based accounts can access premium content. another example wocould be a news page that wowould display an "add" button for adding news links if the current user is in the "Administrator" role. this section describes how write for such scenarios.
TheIprincipal
Interface, whichGenericprincipal
Class we used above implements, has a method calledIsinrole ()
, Which takes a string designating the role to check. so, if we only want to display content if the currently logged-on user is in the "Administrator" role, our page wowould look something like this:
<HTML>
Now the link to the administrators area of the web site will only show up if the current user is logged in and is in the "Administrator" role. if this is a public page, you should provide a link to the login page, optionally setting the querystring variable calledReturnurl
To the path on the server you want the user to return to upon successful authentication.
Summary
This tutorial was created to help you understand the important of Role-based security, as well as implement role-based security on your web site with ASP. net. it's not a hard mechanism to implement, but it does require some know-how of what principals are, how credentials are authenticated, and how users/roles are authorized. I hope you have found this tutorial helpful and interesting, and that I T leads you to implement role-based forms authentication on your current or upcoming site!