MOSS 2007 и LdapRoleProvider

Forms аутентификация очень популярна среди разработчиков порталов на базе MOSS.

Одним из самых интересных способов ее реализации основан на использовании провайдеров из пространства имен Microsoft.Office.Server.Security:

  • LDAPMembershipProvider:
  • LdapRoleProvider.

Данные провайдеры позволяют использовать каталоги LDAP как базы данных для хранения пользователей системы.

Не смотря на многочисленные источники с описанием настройки данного механизма аутентификации, существуют проблемы с применением провайдера LdapRoleProvider совместно с MOSS для использования ролей.

Одним из способов обхода данной проблемы является наследование классу LdapRoleProvider и переопределение метода GetRolesForUser, который почему-то иногда отказывается работать корректно.

Вот псевдокод класса, который исправляет возможную ошибку работы стандартного провайдера:

    public class LdapRolesProvider : Microsoft.Office.Server.Security.LdapRoleProvider
    {

//**************************************************
// Вложенные классы
//**************************************************
        #region Вложенные классы
        class LdapRoleProviderCache
        {
            // Fields
            private string[] roleNames;
            // Methods
            internal LdapRoleProviderCache(string[] roleNames)
            {
                this.roleNames = roleNames;
            }
            // Properties
            internal string[] RoleNames
            {
                get
                {
                    return this.roleNames;
                }
            }
        }
        #endregion Вложенные классы
//**************************************************
// MOSS.LdapRoleProvider
//**************************************************
        #region MOSS.LdapRoleProvider
        /// <summary>
        /// Получить роли для пользователя
        /// </summary>
        /// <param name="username">Имя пользователя</param>
        /// <returns></returns>
        public override String[] GetRolesForUser(String username)
        {
            String[] roleNames                        = null;
            String key                                = "__LDAPROLEPROVIDER__" + this.Name + "_" + username;
            HttpContext current                        = HttpContext.Current;
            if (null != current)
            {
                LdapRoleProviderCache cache            = (LdapRoleProviderCache)current.Cache.Get(key);
                if (cache != null)
                {
                    return cache.RoleNames;
                }
            }
            List<Group> groups                        = Group.GetUserGroups(username); // Тут логика которая получает список ролей пользователя. Можно найти массу реализаций в Интернете.
            List<String> tmpRoleNames                = new List<String>();
            //roleNames = (from g in groups select g.Login).ToArray();
            for (Int32 i = 0; i < groups.Count; ++i)
            {
                tmpRoleNames.Add(groups[i].DisplayName);
                groups[i].Dispose();               
            }
            roleNames                                = tmpRoleNames.ToArray();
            if (current != null)
            {
                current.Cache.Insert(key, new LdapRoleProviderCache(roleNames), null, DateTime.Now.AddMinutes((double)30.0), Cache.NoSlidingExpiration);
            }
            return (roleNames);
        }
        #endregion MOSS.LdapRoleProvider

 

После реализации данного метода, проблема определения ролей исчезает.

Кроме того, можно использовать стандартный синтаксис описания провайдера в файле конфигурации.

<roleManager defaultProvider="LDAPRoles" enabled="true" cacheRolesInCookie="true" cookieName=".PeopleDCRole">
      <providers>        <add name="LDAPRoles"
                         type="LdapRolesProvider, Dal, Version=2008.4.22.1, Culture=neutral, PublicKeyToken=XXXXXXXXX"
                         server="dc.ru" port="389" useSSL="false" groupContainer="OU=UserRoles,OU=X,DC=Y,DC=Z,DC=ru"
                         groupNameAttribute="cn" groupMemberAttribute="member" useUserDNAttribute="false" userNameAttribute="sAMAccountName" dnAttribute="distinguishedName"
                         groupFilter="(ObjectClass=group)" scope="Subtree" />
      </providers>