using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Configuration.Provider;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Web.Security;
using App_Code.DAL;
namespace App_Code.BLL
{
public class ActiveDirectoryRoleProvider : RoleProvider
{
private const string ERROR_ACTIVEDIRECTORY_QUERY = "error query Active Directory.";
private const string ERROR_ROLE_NOT_FOUND = "role not found.";
private const string ERROR_CONFIG_NOT_FOUND = "config not find.";
private const string ERROR_CONNSTR_NOT_FOUND = "can not find 'connectionString'.";
private const string ALL_GROUPS =
"(&(objectCategory=group)(|(groupType=-2147483646)(groupType=-2147483644)(groupType=-2147483640)))";
//private const string GROUPS = "(&(objectClass=group)(cn={0}))";
private const string GROUPS = "(&(objectClass=group)(cn=*emite*))";
private const string USERS = "(&(objectClass=user)(sAMAccountName={0}))";
public override string ApplicationName { get; set; }
private static string getDomain()
{
return ConfigurationManager.ConnectionStrings["ADMembershipProvider"].ConnectionString.Replace("LDAP://", "");
}
private static DirectoryEntry getRoot()
{
return new DirectoryEntry(ConfigurationManager.ConnectionStrings["ADMembershipProvider"].ConnectionString);
}
private static string[] Search(String filter, String field)
{
var res = new List<string>();
var searcher = new DirectorySearcher {SearchRoot = getRoot(), Filter = filter};
searcher.PropertiesToLoad.Clear();
searcher.PropertiesToLoad.Add(field);
searcher.PageSize = 500;
try
{
using (SearchResultCollection results = searcher.FindAll())
{
foreach (SearchResult result in results)
{
int resultCount = result.Properties[field].Count;
for (int c = 0; c < resultCount; c++)
res.Add(result.Properties[field][c].ToString());
}
}
}
catch (Exception ex)
{
throw new ProviderException(ERROR_ACTIVEDIRECTORY_QUERY, ex);
}
return res.Count > 0 ? res.ToArray() : new string[0];
}
public override void Initialize(string name, NameValueCollection config)
{
base.Initialize(name, config);
}
public override bool IsUserInRole(string username, string roleName)
{
string[] roles = GetRolesForUser(username);
return roles.Any(role => role.Equals(roleName, StringComparison.OrdinalIgnoreCase));
}
public override string[] GetRolesForUser(string username)
{
var allRoles = new List<string>();
var root = new DirectoryEntry(ConfigurationManager.ConnectionStrings["ADMembershipProvider"].ConnectionString);
var searcher = new DirectorySearcher(root)
{
Filter = String.Format("(SAMAccountName={0})", username)
};
searcher.PropertiesToLoad.Add("memberof");
SearchResult result = searcher.FindOne();
if (result != null && !string.IsNullOrEmpty(result.Path))
{
DirectoryEntry user = result.GetDirectoryEntry();
PropertyValueCollection groups = user.Properties["memberof"];
string[] Rgroups = GetAllRoles();
foreach (string path in groups)
{
string[] parts = path.Split(',');
if (parts.Length > 0)
{
foreach (string part in parts)
{
string[] p = part.Split('=');
if (p[0].Equals("cn", StringComparison.OrdinalIgnoreCase))
{
foreach (string group in Rgroups)
{
if (group == p[1])
{
string[] r = p[1].Split('-');
if (r[1] == "Admin")
{
string isnullRole = "select count(1) from Users where loginname='" + username +
"' and role is not null";
int confirm = DbConnector.GenerateScalar_Int(isnullRole);
if (confirm == 0)
{
string upd = "update Users set role='admin' where loginname='" + username + "'";
DbConnector.runSql(upd);
}
allRoles.Add("admin");
}
else if (r[1] == "Users")
{
string isnullRole = "select count(1) from Users where loginname='" + username +
"' and role is not null";
int confirm = DbConnector.GenerateScalar_Int(isnullRole);
if (confirm == 0)
{
string upd = "update Users set role='user' where loginname='" + username + "'";
DbConnector.runSql(upd);
allRoles.Add("user");
}
else
{
string leader = "select count(1) from Users where loginname='" +
username + "' and role='leader'";
int confleader = DbConnector.GenerateScalar_Int(leader);
if(confleader>0)
allRoles.Add("leader");
else
allRoles.Add("user");
}
}
}
}
}
}
}
}
}
//if fails to retrieve roles, try from sql db
string[] userdomains = allRoles.Count == 0 ? EmiteData.GetAllRoles(username) : allRoles.ToArray();
return userdomains;
}
public override void CreateRole(string roleName)
{
throw new NotImplementedException();
}
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
throw new NotImplementedException();
}
public override bool RoleExists(string roleName)
{
return GetAllRoles().Any(role => roleName == role);
}
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override string[] GetUsersInRole(string roleName)
{
if (!RoleExists(roleName))
throw new ProviderException(String.Format(ERROR_ROLE_NOT_FOUND, roleName));
var results = new List<string>();
using (var context = new PrincipalContext(ContextType.Domain, null, getDomain()))
{
try
{
GroupPrincipal p = GroupPrincipal.FindByIdentity(context, IdentityType.SamAccountName, roleName);
PrincipalSearchResult<Principal> users = p.GetMembers(true);
foreach (UserPrincipal user in users)
results.Add(user.SamAccountName);
}
catch (Exception ex)
{
throw new ProviderException(ERROR_ACTIVEDIRECTORY_QUERY, ex);
}
}
return results.ToArray();
}
public override string[] GetAllRoles()
{
var results = new List<string>();
string[] roles = Search(GROUPS, "samAccountName");
foreach (string role in roles)
results.Add(role);
return results.ToArray();
}
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
if (!RoleExists(roleName))
throw new ProviderException(String.Format(ERROR_ROLE_NOT_FOUND, roleName));
var results = new List<string>();
using (var context = new PrincipalContext(ContextType.Domain, null, getDomain()))
{
try
{
using (
GroupPrincipal p = GroupPrincipal.FindByIdentity(context, IdentityType.SamAccountName, roleName)
)
{
PrincipalSearchResult<Principal> users = p.GetMembers(true);
foreach (UserPrincipal user in users)
if (user.SamAccountName.IndexOf(usernameToMatch) > 0)
results.Add(user.SamAccountName);
}
}
catch (Exception ex)
{
throw new ProviderException(ERROR_ACTIVEDIRECTORY_QUERY, ex);
}
}
return results.ToArray();
}
}
}
在對用戶進行驗證角色的時候,由於存在兩種provider,而且默認的只有一個,所以需要在默認的rolemanager裏寫能共用的provider。