I found this great blog posting by Scott Guthrie regarding how to use the ASP.NET Membership Roles with Windows Authentication. In this scenario users don’t have to login because Windows Authentication (I knew it as Integrated Security, but I don’t know where I got that name :). This works well with Internet Explorer and Intranet environments. The scenario also dictates that the roles are defined in SQL Server tables instead of Active Directory. Beyond that, Scott’s blog posting (noted above) explains the scenario very well.
Scott’s example goes into more functionality than I will here. However, I do cover how to create the supporting SQL tables and stored procedures and he doesn’t, but he does link to a page that does. He covers how to due Security Trimming of menus, admin interface, automatically creating the roles, etc. If you need details on those things please check ScottGu’s Blog: Implementing Role Based Security with ASP.NET using Windows Authentication and SQL Server. I have to give nearly all credit for the source of all my knowledge to Scott’s blog posting. NOTE: Scott also includes a link to download a working website project.
I want to give the basic steps only. I assume you have a website that just has a default web.config and thus default security.
Step 1: Enable Windows Authentication
Add the authentication and authorization tags to your web.config under the system.web tag. This will require all users to be authenticated. Be sure to enable Windows Integrated Authentication in IIS.
<system.web>
… <authentication mode="Windows"/> <authorization> <deny users="?"/> </authorization>
Step 2: Configure for SQL Server
By default Visual Studio wants to use SQL Express instead of SQL Server. Really, the only thing that Visual Studio needs is to know where the ASP.NET Membership provider database is located. To tell Visual Studio where to connect to SQL Server, add the following (modify for your database location, etc) to your web.config.
<connectionStrings> <remove name="LocalSqlServer"/> <add name="LocalSqlServer" connectionString="Data Source=(local);Initial Catalog=MyDB;Integrated Security=True" providerName="System.Data.SqlClient"/>
Please note, the name LocalSqlServer is required, do not change this.
Step 3: Create supporting tables in SQL Server database
The roles membership table and stored procedures requires tables to be created in a database. This can be in your application database, or it can be in a separate database. There may be an easier way to create these tables and stored procedures, but this works well, but it is a bit of an obscure location for the .exe.
If you are using .NET 2.0 or greater (yes v3.0 and v3.5 and v3.5.1 also) the .exe you need to execute is located in a path similar to the following:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql.exe
aspnet_regsql.exe -E -S myServer -d MyDB -A m -A rYou can also run the aspnet_regsql.exe without parameters and a wizard will run. The wizard does NOT allow you to only install certain features, it installs all the features. Use the command line with args or use the less flexible, but prettier wizard. Your choice.
Step 4: Enable SQL based Role Management
Replace this line in your web.config
<roleManager enabled="true" />
<roleManager enabled="true" defaultProvider="SqlRoleManager">
<providers>
<clear/>
<add name="SqlRoleManager" type="System.Web.Security.SqlRoleProvider" connectionStringName="LocalSqlServer"/>
</providers>
</roleManager>
void Application_Start(object sender, EventArgs e)
{
if (!Roles.RoleExists("Admin"))
{
Roles.CreateRole("Admin");
}
}
if (!Roles.IsUserInRole(userName, roleName))
{
Roles.AddUserToRole(userName, roleName);
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Security;
namespace MyApp
{
public partial class UserAdmin : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void PopulateRoleList(string username)
{
RoleList.Items.Clear();
string[] roleNames = Roles.GetAllRoles();
foreach (string roleName in roleNames)
{
ListItem roleListItem = new ListItem();
roleListItem.Text = roleName;
roleListItem.Selected = Roles.IsUserInRole(username, roleName);
RoleList.Items.Add(roleListItem);
}
}
protected void UpdateRolesFromList()
{
foreach (ListItem roleListItem in RoleList.Items)
{
string roleName = roleListItem.Value;
string userName = TxtUserName.Text;
bool enableRole = roleListItem.Selected;
if (enableRole && !Roles.IsUserInRole(userName, roleName))
{
Roles.AddUserToRole(userName, roleName);
}
else if (!enableRole && Roles.IsUserInRole(userName, roleName))
{
Roles.RemoveUserFromRole(userName, roleName);
}
}
}
protected void LookupBtn_Click(object sender, EventArgs e)
{
PopulateRoleList(TxtUserName.Text);
UpdateBtn.Visible = true;
}
protected void UpdateBtn_Click(object sender, EventArgs e)
{
UpdateRolesFromList();
PopulateRoleList(TxtUserName.Text);
}
}
}
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeBehind="UserAdmin.aspx.cs" Inherits="MyApp.UserAdmin" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<h3>Role Manager</h3>
<div>
Enter UserName:
<asp:TextBox ID="TxtUserName" runat="server"></asp:TextBox>
<asp:Button ID="LookupBtn" runat="server" Text="Search"
onclick="LookupBtn_Click" />
</div>
<div class="roleList">
<asp:CheckBoxList ID="RoleList" runat="server">
</asp:CheckBoxList>
</div>
<div>
<asp:button ID="UpdateBtn" text="Update" Visible="false" runat="server"
onclick="UpdateBtn_Click" />
</div>
</asp:Content>
<authorization>
<deny users="?"/>
<allow roles="Admin"/>
</authorization>
<configuration>
<location path="Review.aspx">
<system.web>
<authorization>
<allow roles="Reviewer,Process Manager"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
* means all users
? means anonymous
It is also important to understand that the allow and deny tags are applied in the order they show in the parent tag. Order matters.
References
- ScottGu’s Blog: Implementing Role Based Security with ASP.NET using Windows Authentication and SQL Server
- From ScottGu’s Blog: Working downloadable demo
- Web.config schema
5 comments:
big thanks for this article i searched more times and this article are the best really thanks you
Anonymous,
That you for the very kind feedback. It is greatly appreciated.
Thanks,
Brent
The problem with Scott's solution (and yours for that matter) is that adding users to roles this way IS A MESS. And surprisingly no one pointed this out. If does not check if the user exists, it takes anything and adds it into SQL as users. So if you are adding someone and misspell their login name you will never know it. This solution will only have any use IF the way to check user name against Active Directory is provided. And I would like to know how it can be done. Otherwise it's pretty useless.
Hi, any working code can be downloaded? I need the C# version not the VB version. Thanks for your help.
Thank you very much.
Very nice article. Very usefull. Works fine.
Post a Comment