Custom Roles with Forms Authentication

for RuBoard

We have discussed so far how to authenticate a user with forms authentication. This process gives you an identity to authorize against. With Windows authentication, you have both an identity and a list of roles to authorize against. How do you use role mappings with forms authentication to authorize against?

With a little work, you can add roles to the forms authentication model. You will use the web.config in Listing 7.11, which defines the roles that are required for access to various URLs in the application.

Listing 7.11 Web.config That Uses Location Mapping and URL Authorization to Map Roles to Application Locations
 <?xml version="1.0" encoding="utf-8" ?> <configuration>     <system.web>         <authentication mode="Forms">             <forms name="FORMURL" loginUrl="login.aspx" protection="All" timeout="30" />         </authentication>         <!--  AUTHORIZATION           This section sets the authorization policies of the application. You can allow or deny access           to application resources by user or role. Wildcards: "*" mean everyone, "?" means anonymous           (unauthenticated) users.     -->         <authorization>             <allow users="*" /> <!-- Allow all users -->             <!--  <allow     users="[comma separated list of users]"                              roles="[comma separated list of roles]"/>                   <deny      users="[comma separated list of users]"                              roles="[comma separated list of roles]"/>             -->         </authorization>     </system.web>     <location path="Administrator">         <system.web>             <authorization>                 <allow roles="Administrator" />                 <deny users="*" />             </authorization>         </system.web>     </location>     <location path="Publisher">         <system.web>             <authorization>                 <allow roles="Administrator" />                 <allow roles="Publisher" />                 <deny users="*" />             </authorization>         </system.web>     </location>     <location path="User">         <system.web>             <authorization>                 <allow roles="Administrator" />                 <allow roles="User" />                 <deny users="*" />             </authorization>         </system.web>     </location> </configuration> 

Next, create another simple login form. It will collect a set of credentials and allow a user with a username of either "Administrator" or "Chris" into the application. Listings 7.12 and 7.13 show the login page.

Listing 7.12 A Login Page for Gathering Credentials That Will Authenticate Only Two Users: Chris and Administrator
 <%@ Page language="c#" Codebehind="login.aspx.cs" AutoEventWireup="false" Inherits="FormAuthorizationURL.login" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > <HTML>     <HEAD>         <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">         <meta name="CODE_LANGUAGE" Content="C#">         <meta name="vs_defaultClientScript" content="JavaScript (ECMAScript)">         <meta name="vs_targetSchema" content="http://schemas.microsoft.com/ intellisense/ie5">     </HEAD>     <body ms_positioning="GridLayout">         <form id="login" method="post" runat="server">             <asp:Label id="lblUserName" style="Z-INDEX: 101; LEFT: 36px; POSITION: absolute; TOP: 43px" runat="server">User Name:</asp:Label>             <asp:Button id="btnLogin" style="Z-INDEX: 105; LEFT: 290px; POSITION: absolute; TOP: 40px" runat="server" Text="Login" tabIndex="4"></asp:Button>             <asp:TextBox id="txtPassword" style="Z-INDEX: 104; LEFT: 119px; POSITION: absolute; TOP: 74px" runat="server" tabIndex="3" TextMode="Password"></asp:TextBox>             <asp:TextBox id="txtUserName" style="Z-INDEX: 102; LEFT: 119px; POSITION: absolute; TOP: 41px" runat="server" tabIndex="1"></asp:TextBox>             <asp:Label id="lblPassword" style="Z-INDEX: 103; LEFT: 36px; POSITION: absolute; TOP: 77px" runat="server" tabIndex="2">Password:</asp:Label>             <asp:RequiredFieldValidator id="RequiredFieldValidator1" style="Z-INDEX: 106; LEFT: 44px; POSITION: absolute; TOP: 131px" runat="server" ErrorMessage="User Name is required." ControlToValidate="txtUserName"></asp:RequiredFieldValidator>             <asp:RequiredFieldValidator id="RequiredFieldValidator2" style="Z-INDEX: 107; LEFT: 46px; POSITION: absolute; TOP: 165px" runat="server" ErrorMessage="Password is required." ControlToValidate="txtPassword"></asp:RequiredFieldValidator>             <asp:Label id="lblMessage" style="Z-INDEX: 108; LEFT: 44px; POSITION: absolute; TOP: 8px" runat="server" Width="285px" Height="19px" ForeColor="Red"></asp:Label>         </form>     </body> </HTML> 
Listing 7.13 The Class File for the Page in Listing 7.12
 using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; using System.Web; using System.Web.SessionState; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; namespace FormAuthorizationURL {     /// <summary>     /// Summary description for login.     /// </summary>     public class login : System.Web.UI.Page     {         protected System.Web.UI.WebControls.Label lblUserName;         protected System.Web.UI.WebControls.Button btnLogin;         protected System.Web.UI.WebControls.TextBox txtPassword;         protected System.Web.UI.WebControls.TextBox txtUserName;         protected System.Web.UI.WebControls.Label lblPassword;         protected System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator1;         protected System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator2;         protected System.Web.UI.WebControls.Label lblMessage;         public login()         {             Page.Init += new System.EventHandler(Page_Init);         }         private void Page_Load(object sender, System.EventArgs e)         {             // Put user code to initialize the page here         }         private void Page_Init(object sender, EventArgs e)         {             //             // CODEGEN: This call is required by the ASP.NET Web Form Designer.             //             InitializeComponent();         }         #region Web Form Designer generated code         /// <summary>         /// Required method for Designer support - do not modify         /// the contents of this method with the code editor.         /// </summary>         private void InitializeComponent()         {             this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click);             this.Load += new System.EventHandler(this.Page_Load);         }         #endregion         private void btnLogin_Click(object sender, System.EventArgs e)         {             switch(txtUserName.Text)             {                 case "Chris":                 case "Administrator":                     System.Web.Security.FormsAuthentication.RedirectFromLoginPage (txtUserName.Text, false);                     break;                 default:                     lblMessage.Text = "Invalid User";                     break;             }         }     } } 

This so far is similar to past examples. Now you need to add one more thing to the mix. Before the authorization process begins, an application event is raised, AuthorizeRequest. By handling this event, you can do some extra work before any page is authorized. In this case, you are going to replace the default principal with a new instance of GenericPrincipal, with one important difference. You are going to fill in the role information. This will allow you to then perform authorization against the roles. The constructor for GenericPrincipal allows you to pass a list of roles into it. After creating the new GenericPrincipal, you will replace the default one with the one you have created.

NOTE

The AuthorizeRequest event is fired for every request, including the initial one when the user isn't authenticated, the one that returns in the login form, and so on. It is a good idea to check whether the user is authenticated prior to attempting to perform the role mapping. This is easily done using the IsAuthenticated property of the identity.


Application events are typically handled in the global.asax. Listing 7.14 shows a global.asax that handles the AuthorizeRequest event. The code first checks to make sure the user is authenticated. If she is, it then maps her into roles based on her identity. A new GenericPrincipal is created with the appropriate role information, and that is it!

Listing 7.14 The global.asax Class That Handles the AuthorizeRequest Application Event
 using System; using System.Collections; using System.ComponentModel; using System.Web; using System.Web.SessionState; namespace FormAuthorizationURL  {     /// <summary>     /// Summary description for Global.     /// </summary>     public class Global : System.Web.HttpApplication     {         protected void Application_AuthorizeRequest(object sender, System.EventArgs e)         {             // Make sure the user is authenticated             if(HttpContext.Current.User.Identity.IsAuthenticated)             {                 // Map the user to a role based on their identity                 switch(HttpContext.Current.User.Identity.Name)                 {                     case "Chris":                         HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(HttpContext.Current.User.Identity, new string[] {"Publisher"});                         break;                     case "Administrator":                         HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(HttpContext.Current.User.Identity, new string[] {"Administrator", "Publisher"});                         break;                     default:                         HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(HttpContext.Current.User.Identity, new string[] {"User"});                         break;                 }             }         }     } } 
for RuBoard


C# Developer[ap]s Guide to ASP. NET, XML, and ADO. NET
C# Developer[ap]s Guide to ASP. NET, XML, and ADO. NET
ISBN: 672321556
EAN: N/A
Year: 2005
Pages: 103

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net