After working on a project that had me write a custom Role Provider for WSS, I thought I would try and help explain some things about what Membership and Role Providers do, and more specifically in regards to SharePoint.
First off, in my case, the user store was Active Directory. When working with MOSS, you can use the LDAP provider for both membership and roles. In WSS however, there is only a default Membership provider, which does not allow for groups to be used, say AllUsers or Domain Users.
Membership Provider – Looks at a user store to find the specific user, by either username, email, etc.
Role Provider – Looks for roles that exist, and what roles a user has, and what users are contained by a role. For our case, Roles are AD Groups.
In my project I had a custom web part that displayed information from an external data source, looking the user information by the user id from a seperate Active Directory instance. This was not the same Domain that the users logged into their computers with, so we had to use FBA.
Now, you do not need a role provider if you do not plan on using groups from AD, but again in my case, we did not plan to add each user to the group or policy for the web application. We leveraged the role provider to be able to use Domain Groups such as Domain Users, and a couple other groups.
Implimenting the interface for "System.Web.Security.RoleProvider"
The documentation is not all that clear, but understand that a Role with regards to Active Directory is simple a Group.
I have not implimented all the methods, just the important ones for my project:
//Looks for the given user in the given Role
public override bool IsUserInRole(string username, string roleName)
{
string[] roles = GetRolesForUser(username);
if (roles.Select(r => r.ToLower() == roleName.ToLower()).Count() > 0)
{
return true;
}
return false;
}
public override string[] GetRolesForUser(string username)
{
try
{
PrincipalContext adPrincipalContext = new PrincipalContext(ContextType.Domain, Domain, ConnectionUsername, ConnectionPassword);
UserPrincipal user = UserPrincipal.FindByIdentity(adPrincipalContext, username);
PrincipalSearchResult results = user.GetAuthorizationGroups();
return results.Select(r => r.SamAccountName.ToLower()).ToArray();
}
catch (Exception ex)
{
Debug.WriteLine("Error getting Roles for User: " + ex.Message);
}
return new string[0]{};
}
public override string[] GetAllRoles()
{
try
{
PrincipalContext adPrincipalContext = new PrincipalContext(ContextType.Domain, Domain, ConnectionUsername, ConnectionPassword);
GroupPrincipal group = new GroupPrincipal(adPrincipalContext); PrincipalSearcher searcher = new PrincipalSearcher();
searcher.QueryFilter = group;
// run the query
PrincipalSearchResult results = searcher.FindAll();
return results.Select(r => r.SamAccountName.ToLower()).ToArray();
}
catch (Exception ex)
{
Debug.WriteLine("Error finding groups: " + ex.Message);
}
return new string[0] { };
}
//Find the role/AD Group by the name
public override bool RoleExists(string roleName)
{
if (String.IsNullOrEmpty(roleName))
{
return false;
}
else
{
try
{
PrincipalContext adPrincipalContext = new PrincipalContext(ContextType.Domain, Domain, ConnectionUsername, ConnectionPassword);
GroupPrincipal group = new GroupPrincipal(adPrincipalContext); group.SamAccountName = roleName;
PrincipalSearcher searcher = new PrincipalSearcher();
searcher.QueryFilter = group;
// run the query
Principal results = searcher.FindOne();
if (results != null)
{
if (results.SamAccountName == roleName)
{
return true;
}
}
//We did not find the name of the Role from the searcher, just to make sure there was not a problem with Case
return GetAllRoles().Contains(roleName.ToLower());
}
catch (Exception ex)
{
Debug.WriteLine("Error looking for Role: " + ex.Message);
}
}
return false;
}
One nice thing to note, is that I used the new .Net objects for finding users in Active Directory.
PrincipalContext, UserPrincipal, GroupPrincipal, and PrincipalSearcher sure do make things easy! They are found under the System.DirectoryServices.AccountManagement namespace.
I have a couple examples of Linq I used as well to make things a bit simpler, and less foreach loops. I have not implimented all of the methods as stated before, you can however impliment as needed, these base methods should get you most of the way there.
Hope you find a use for it, and let me know if it helps.