Have you ever come across a situation where you want to have multiple login pages with Forms Authentication. Forms Authentication directly supports one login page, but there is a work around. Today we will see how to achieve this.
For an example let’s say you want two login pages where one is for administrators and other is for customers.
Default.aspx |
When the user clicks on Admin, he should be redirected to administrators’ content where the user will have to authenticate himself as an administrator. When the user clicks on Customer, he will be redirected to customers’ content again where the user will have to authenticate himself as a customer. Administrators login page will have some different content and customers login page will have some other.
Admin Login Page |
Customer Login Page |
I have a web application and I have two folders inside my project. One is for Administrators and the other is for Customers. I will create a login page and a sample page inside Admin folder and create another login page and a sample page inside Customer folder. Here is what I have after completing previous steps.
Folders inside Solution Explorer |
For demonstration purposes in my admin login page I have a drop down where I can select which type of credentials I am going to try in admin login. If login with admin credentials I should be able to see admin content. If I login with customer credentials, I should prompted with admin login again.
Admin Login Page |
protected void Button1_Click(object sender, EventArgs e)
Next I am modifying the global.asax file. I am adding the “Application_AuthenticateRequest” event.{ string userData = ""; string userName = ""; if (DropDownList1.SelectedIndex == 0) // admin { userData = "Admin"; // set userData userName = "Admin User Name"; } else if (DropDownList1.SelectedIndex == 1) //customer { userData = "Customer"; // set userData userName = "Customer User Name"; } // initialize FormsAuthentication FormsAuthentication.Initialize(); // create a new ticket used for authentication FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddMinutes(15), false, userData); // encrypt the cookie using the machine key for secure transport string encTicket = FormsAuthentication.Encrypt(authTicket); // create and add the cookies to the list for outgoing response HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket); Response.Cookies.Add(faCookie); Response.Redirect("/Admin/WebForm1.aspx"); }
protected void Application_AuthenticateRequest(object sender, EventArgs e)
Now I am modifying the “web.config” file as follows.{ if (HttpContext.Current.User != null) { if (HttpContext.Current.User.Identity.IsAuthenticated) { if (HttpContext.Current.User.Identity is FormsIdentity) { //HttpCookie cookie = HttpContext.Current.Request.Cookies["UserRole"]; FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity; FormsAuthenticationTicket ticket = id.Ticket; // get the stored user-data, in this case it's our users' role information string userData = ticket.UserData; string[] roles = userData.Split(','); HttpContext.Current.User = new GenericPrincipal(id, roles); } } } }
<authentication mode="Forms">
<forms name="LoginCookie" loginUrl="Login.aspx" protection="None" path="/" defaultUrl="Login.aspx" timeout="30" /> </authentication> <authorization> <deny users="?" /> </authorization>
Now I need to secure directories with role based Forms Authentication. For that again I am modifying the “web.config” file as follows.
<!--for admin folder allow users having the role 'Admin' and deny other-->
<location path="Admin" allowOverride="true"> <system.web> <authorization> <allow roles="Admin" /> <deny users="*"/> </authorization> </system.web> </location> <!--for content folder allow all--> <location path="Content" allowOverride="true"> <system.web> <authorization> <allow users="*" /> </authorization> </system.web> </location> <!--for scripts folder allow all--> <location path="Scripts" allowOverride="true"> <system.web> <authorization> <allow users="*" /> </authorization> </system.web> </location> <!--for images folder allow all--> <location path="Images" allowOverride="true"> <system.web> <authorization> <allow users="*" /> </authorization> </system.web> </location> <!--for login.aspx allow all--> <location path="Login.aspx" allowOverride="true"> <system.web> <authorization> <allow users="*"/> </authorization> </system.web> </location> <!--for default.aspx allow all--> <location path="Default.aspx" allowOverride="true"> <system.web> <authorization> <allow users="*"/> </authorization> </system.web> </location> <!--for Admin/Login.aspx allow all--> <location path="Admin/Login.aspx" allowOverride="true"> <system.web> <authorization> <allow users="*"/> </authorization> </system.web> </location> <!--for Customer/Login.aspx allow all--> <location path="Customer/Login.aspx" allowOverride="true"> <system.web> <authorization> <allow users="*"/> </authorization> </system.web> </location>
As you saw above loginUrl in the forms element can be only one. So I have created a page inside root called “Login” and I am not interested in the design of that page. Just in Page_Load event I am writing the following code. In here what I am doing is, when the main login page is loading it will identify the request type (admin or customer) by analysing the url and redirect to the relevant login page.
protected void Page_Load(object sender, EventArgs e)
Now I am all set. In my Default.aspx, I have two hyperlinks for admin content and customer content.{ char[] character = { '/' }; if (Request["ReturnUrl"] != null) { // Request["ReturnUrl"].ToString() -> // http://localhost:1965/Admin/Login.aspx; // http://localhost:1965/Customer/Login.aspx string[] strs = Request["ReturnUrl"].Split(character); // if the second part is Admin go to admin login if (strs[1] == "Admin") { Response.Redirect(@"/Admin/Login.aspx"); } // if the second part is Customer go to customer login else if (strs[1] == "Customer") { Response.Redirect(@"/Customer/Login.aspx"); } } }
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Admin/WebForm1.aspx">Admin</asp:HyperLink>
So in the admin login when I logged in with admin credentials I can see the admin content. If I logged in with customer credentials I will be redirected to admin login page again.<br /> <asp:HyperLink ID="HyperLink2" runat="server" NavigateUrl="~/Customer/WebForm1.aspx">Customer</asp:HyperLink>
Admin Can View Admin Content |
Customer Can't View Admin Content |
I am not going to show you how to do this for the customer’s login page. The concept is the same. You can download the sample project from my skydrive and try this out.
Hope this helps.
Happy Coding.
Regards,
Jaliya
good day, is there an option to get the sample you used for this Demo? i tried the links from this post and from https://social.technet.microsoft.com/wiki/contents/articles/19740.forms-authentication-with-multiple-login-pages.aspx but files are not there anymore.
ReplyDeleteHi Christian,
DeleteYeah, MSDN Code Gallery is now retired. Can you send me an email on jaliya.udagedara@gmail.com, and I will send you the code sample.
Cheers,
Jaliya
This comment has been removed by the author.
Delete