Notes for the Role Provider webinars
- Visual Studio – admin
- Microsoft SQL Server Management Studio
- Virtual PC – Windows Server VHD
- Softerra LDAP Browser
- Delete profile from LDAP Browser
Overview ASP.NET Membership & Role Providers
The Membership and Role Provider model was introduced with ASP.NET 2.0.
--
Overview of User Management in Sitefinity
The Administrator role is created by default and granted Unrestricted access in the ~/web.config:
<security defaultProvider="DefaultSecurityProvider" cmsProvidersName="Sitefinity">
<roles>
<clear/>
<add name="Administrators" permission="Unrestricted"/>
</roles>
</security>
Additional Unrestricted roles can be added by adding additional Roles.
Roles permissions are also configured inside Sitefinity:
- Administration –> Users (Roles)
- Administration –> Permissions
- Modules –> Blogs –> Permissions
- Pages –> Permissions
There are two types of Membership Providers offered in Sitefinity:
Default Sitefinity Security Providers
- Telerik.DataAccess.AspnetProviders.TelerikMembershipProvider
- Telerik.Security.ActiveDirectory.TelerikRoleProvider
Active Directory Sitefinity Security Providers
- Telerik.DataAccess.AspnetProviders.TelerikADRoleProvider
- Telerik.Security.ActiveDirectory.TelerikADMembershipProvider
--
Adding Custom Fields to the Sitefinity Membership Provider
Modify ~/web.config to contain mappings for custom fields:
<configuration>
<system.web>
<profile defaultProvider="Sitefinity">
<properties>
<add name="Address"/>
<add name="City"/>
<add name="State"/>
<add name="Zip"/>
</properties>
</profile>
</system.web>
</configuration>
Modify ~/Sitefinity/Admin/CmsAdmin/Users.aspx to contain new fields:
<cc1:ManageUsers runat="server" ID="manageUsers">
<ListTemplate>
<!-- Insert Form Elements for new Fields -->
</ListTemplate>
<InsertTemplate>
<!-- Insert Form Elements for new Fields -->
</InsertTemplate>
<EditTemplate>
<!-- Insert Form Elements for new Fields -->
</EditTemplate>
</cc1:ManageUsers>
Insert form fields for new custom fields into ~/Sitefinity/Admin/CmsAdmin/Users.aspx:
<li>
<cc2:FieldLabel ID="lblAddress" Text="Address" runat="server" />
<asp:TextBox ID="Address" runat="server" />
</li>
<li>
<cc2:FieldLabel ID="lblCity" Text="City" runat="server" />
<asp:TextBox ID="City" runat="server" />
</li>
<li>
<cc2:FieldLabel ID="lblState" Text="State" runat="server" />
<asp:TextBox ID="State" runat="server" />
</li>
<li>
<cc2:FieldLabel ID="lblZip" Text="Zip" runat="server" />
<asp:TextBox ID="Zip" runat="server" />
</li>
Insert form fields for new custom fields into ~/Sitefinity/Admin/CmsAdmin/MyProfile.aspx:
<li>
<cc2:FieldLabel ID="lblAddress" Text="Address" runat="server" />
<asp:TextBox ID="Address" runat="server" />
</li>
<li>
<cc2:FieldLabel ID="lblCity" Text="City" runat="server" />
<asp:TextBox ID="City" runat="server" />
</li>
<li>
<cc2:FieldLabel ID="lblState" Text="State" runat="server" />
<asp:TextBox ID="State" runat="server" />
</li>
<li>
<cc2:FieldLabel ID="lblZip" Text="Zip" runat="server" />
<asp:TextBox ID="Zip" runat="server" />
</li>
--
Overview of the Active Directory
Setup an Active Directory for Testing
Setup users and roles in Active Directory Users and Computers
- Log into VHD Server as Administrator
- Manage Users and Computers in Active Directory
Test connection to AD from local computer:
- Use Softerra’s LDAP Browser to test connection and credentials
- Create new Profile
- Hostname: WS03R2EE (your Virtual Server's hostname)
- Base: DC=SitefinityWatch,DC=local
- Username: SitefinityWatch\Administrator
Sample LDAP queries:
- Finds the Administrator account:
(&(sAMAccountType=805306368)(sAMAccountName=Administrator))
- Find the Administrators role:
(&(objectClass=group)(sAMAccountName=Administrators))
- Finds all user accounts:
sAMAccountType=805306368
- Finds all account roles:
(objectClass=group)
--
Enabling Sitefinity Active Directory Integration
Enabling Sitefinity Active Directory integration requires 3 steps:
- Create <connectionString> to Active Directory
- Create <roleManager> to TelerikADRoleManager
- Create <membership> to TelerikADMembershipManager
Sitefinity’s Active Directory Membership and Role Provider is configured in the ~/web.config:
<configuration>
<connectionStrings>
<add name="ADService" connectionString="LDAP://WS03R2EE/DC=SitefinityWatch,DC=local" />
</connectionStrings>
<system.web>
<roleManager enabled="true" cacheRolesInCookie="true" defaultProvider="Sitefinity">
<providers>
<clear />
<add applicationName="/" description="Telerik Role provider for Active Directory"
connectionStringName="ADService"
connectionUsername="Administrator"
connectionPassword="Evaluation1"
domainName="WS03R2EE"
searchScope="subtree"
name="Sitefinity"
type="Telerik.Security.ActiveDirectory.TelerikADRoleProvider, Telerik.Security" />
</providers>
</roleManager>
<membership defaultProvider="Sitefinity" userIsOnlineTimeWindow="15" hashAlgorithmType="">
<providers>
<clear/>
<add name="Sitefinity"
connectionStringName="ADService"
enableSearchMethods="true"
attributeMapUsername="sAMAccountName"
connectionUsername="Administrator"
connectionPassword="Evaluation1"
type="Telerik.Security.ActiveDirectory.TelerikADMembershipProvider, Telerik.Security"/>
</providers>
</membership>
</system.web>
</configuration>
Full explanation of the Telerik Active Directory Membership and Role providers.
<roleManager enabled="true" cacheRolesInCookie = "true" defaultProvider = "Sitefinity">
<providers>
<clear/>
<add name="Sitefinity"
applicationName="/"
description="Telerik Role provider for Active Directory"
authenticationType="Secure"
userSearchFilter="(&(sAMAccountType=805306368)(sAMAccountName={0}))"
roleSearchFilter="(&(objectClass=group)(sAMAccountName={0}))"
userDefinitionFilter="sAMAccountType=805306368"
groupDefinitionFilter="(objectClass=group)"
connectionStringName="ActiveDirectory"
type="Telerik.Security.ActiveDirectory.TelerikADRoleProvider, Telerik.Security"
connectionUsername="username"
connectionPassword="password"
groupMaps="Administrators, Users"
domainName="telerik.com"
searchScope="subtree"
/>
</providers>
</roleManager>
--
Creating a custom Membership and Role Provider
Add project references to the following assemblies:
- System.Configurations
- System.Web
MembershipProvider.cs
using System.Configuration.Provider;
using System.Linq;
using Telerik.OpenAccess;
namespace SitefinityWatch.Security
{
public class MembershipProvider : System.Web.Security.MembershipProvider
{
}
}
RoleProvider.cs
using System.Configuration.Provider;
using System.Linq;
using Telerik.OpenAccess;
namespace SitefinityWatch.Security
{
public class RoleProvider : System.Web.Security.RoleProvider
{
}
}
--
Creating a custom Role Provider for use with Active Directory
Create Roles database table:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Roles](
[ID] [uniqueidentifier] NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Roles] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Roles] ADD CONSTRAINT [DF_Roles_ID] DEFAULT (newid()) FOR [ID]
GO
Create MemberRoles database table:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[MemberRoles](
[ID] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[Username] [varchar](50) NOT NULL,
[RoleID] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_MemberRoles] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[MemberRoles] WITH CHECK ADD CONSTRAINT [FK_MemberRoles_Roles] FOREIGN KEY([RoleID])
REFERENCES [dbo].[Roles] ([ID])
GO
ALTER TABLE [dbo].[MemberRoles] CHECK CONSTRAINT [FK_MemberRoles_Roles]
GO
ALTER TABLE [dbo].[MemberRoles] ADD CONSTRAINT [DF_MemberRoles_ID] DEFAULT (newid()) FOR [ID]
GO
Use OpenAccess ORM reverse mapping to create:
Use OpenAccess ORM forward mapping to generate GUIDs for Primary Keys
- Generate new GUIDs for new Roles
- Generate new GUIDs for new MemberRoles
RoleManager.cs
using System.Collections.Generic;
using System.Linq;
using Telerik.OpenAccess;
using Telerik.OpenAccess.Query;
namespace SitefinityWatch.Security
{
public class RoleManager
{
private IObjectScope scope;
public RoleManager()
: this(ObjectScopeProvider1.GetNewObjectScope())
{
}
public RoleManager(IObjectScope _scope)
{
scope = _scope;
}
public void AddUserToRole(string username, string roleName)
{
if (RoleExists(roleName))
{
if (!IsUserInRole(username, roleName))
{
var role = scope.Extent<Role>().First(r => r.Name == roleName);
var memberRole = new MemberRole();
memberRole.Role = role;
memberRole.Username = username;
scope.Transaction.Begin();
scope.Add(memberRole);
scope.Transaction.Commit();
}
}
}
public bool RoleExists(string roleName)
{
return (from r in scope.Extent<Role>()
where r.Name == roleName
select r).Any();
}
public bool IsUserInRole(string username, string roleName)
{
return (from r in scope.Extent<MemberRole>()
where r.Username == username && r.Role.Name == roleName
select r).Any();
}
public void CreateRole(string roleName)
{
if (!RoleExists(roleName))
{
var role = new Role
{
Name = roleName
};
scope.Transaction.Begin();
scope.Add(role);
scope.Transaction.Commit();
}
}
public void DeleteRole(string roleName)
{
if (RoleExists(roleName))
{
var role = scope.Extent<Role>().First(r => r.Name == roleName);
scope.Transaction.Begin();
scope.Remove(role);
scope.Transaction.Commit();
}
}
public string[] FindUsernamesInRole(string roleName, string usernameToMatch)
{
return (from r in scope.Extent<MemberRole>()
where r.Role.Name == roleName && r.Username.Contains("usernameToMatch")
select r.Username).ToArray();
}
public bool RoleHasMembers(string roleName)
{
var query = from r in scope.Extent<MemberRole>()
where r.Role.Name == roleName
select r;
return query.Any();
}
public void RemoveAllRoleMembers(string roleName)
{
var query = from r in scope.Extent<MemberRole>()
where r.Role.Name == roleName
select r;
scope.Transaction.Begin();
scope.Remove(query);
scope.Transaction.Commit();
}
public List<Role> GetAllRoles()
{
var query = from r in scope.Extent<Role>()
orderby r.Name
select r;
return query.ToList();
}
public List<Role> GetRolesForUser(string username)
{
var query = from r in scope.Extent<MemberRole>()
where r.Username == username
orderby r.Role.Name
select r.Role;
return query.ToList();
}
public string[] GetUsersInRole(string roleName)
{
var query = (from r in scope.Extent<MemberRole>()
where r.Role.Name == roleName
select r.Username).ToArray();
return query.ToArray();
}
public void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
var usernamesList = new List<string>(usernames);
var rolenamesList = new List<string>(roleNames);
var query = from r in scope.Extent<MemberRole>()
where usernamesList.Contains(r.Username) && rolenamesList.Contains(r.Role.Name)
select r;
scope.Transaction.Begin();
scope.Remove(query);
scope.Transaction.Commit();
}
}
}
RoleProvider.cs
using System.Configuration.Provider;
using System.Linq;
using Telerik.OpenAccess;
namespace SitefinityWatch.Security
{
public class RoleProvider : System.Web.Security.RoleProvider
{
private string _applicationName;
private IObjectScope scope;
private RoleManager _manager;
public RoleManager manager
{
get
{
if (_manager == null)
{
_manager = new RoleManager();
}
return _manager;
}
}
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
foreach (string username in usernames)
{
foreach (string role in roleNames)
{
manager.AddUserToRole(username, role);
}
}
}
public override string ApplicationName
{
get
{
return _applicationName;
}
set
{
_applicationName = value;
}
}
public override void CreateRole(string roleName)
{
manager.CreateRole(roleName);
}
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
if (manager.RoleHasMembers(roleName))
{
if (throwOnPopulatedRole)
{
throw new ProviderException(roleName + " has members!");
}
manager.RemoveAllRoleMembers(roleName);
}
manager.DeleteRole(roleName);
return true;
}
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
return manager.GetUsersInRole(roleName);
}
public override string[] GetAllRoles()
{
var query = from r in manager.GetAllRoles()
select r.Name;
return query.ToArray();
}
public override string[] GetRolesForUser(string username)
{
if (username == "admin" || username == "Administrator")
{
return new string[] { "Administrators" };
}
var query = from r in manager.GetRolesForUser(username)
select r.Name;
return query.ToArray();
}
public override string[] GetUsersInRole(string roleName)
{
return manager.GetUsersInRole(roleName);
}
public override bool IsUserInRole(string username, string roleName)
{
if ((username == "Administrator" && roleName == "Administrators") || (username == "admin" && roleName == "Administrators"))
{
return true;
}
return manager.IsUserInRole(username, roleName);
}
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
manager.RemoveUsersFromRoles(usernames, roleNames);
}
public override bool RoleExists(string roleName)
{
return manager.RoleExists(roleName);
}
}
}
Add references to the following:
- System.Configuration
- System.Web
~/web.config
<configuration>
<connectionStrings>
<add name="ADService" connectionString="LDAP://WS03R2EE/DC=SitefinityWatch,DC=local" />
</connectionStrings>
<system.web>
<roleManager enabled="true" cacheRolesInCookie="true" defaultProvider="Sitefinity">
<providers>
<clear />
<add applicationName="/" name="Sitefinity" type="SitefinityWatch.Security.RoleProvider, SitefinityWatch.Security"/>
</providers>
</roleManager>
</system.web>
</configuration>
--
More Resources: