[ELMA3] Изменение работы сервиса управления учетными записями пользователей в версии 3.11
1. Используемые термины
Провайдер – старый вариант компонента, реализующего авторизацию. В 3.11 поддерживается, но не рекомендуется для написания новых расширений.
Модуль – новый вариант компонента, реализующего авторизацию. Позволяет создавать экземпляры подключений к внешним хранилищам учетных данных прямо из веб-интерфейса. На момент выпуска 3.11.0 доступны два модуля: LDAP и Active Directory. Возможно написание своего модуля авторизации, отличного от LDAP.
Экземпляр модуля – набор настроек подключения к модулю авторизации.
2. Перенос настроек системного провайдера авторизации в LDAP
При обновлении ELMA на версию 3.11 системный провайдер авторизации в LDAP будет удален. Вместо него будет создан экземпляр модуля LDAP, в которые будут автоматически перенесены настройки удаленного провайдера.
3. Обновление собственного провайдера авторизации
В версии 3.11 работа провайдеров авторизации поддерживается, но для возможности авторизации пользователей необходимо внести изменения в код.
Метод void Validating(UserValidationContext context) обработчика событий авторизации в системе EleWise.ELMA.Security.Services.IMembershipServiceEventHandler больше не используется для валидации, результаты его выполнения занесенные в context учитываться не будут. Вместо него валидация проводится в методе bool ValidateUser(string userNameOrEmail, string password) точки расширения реализации внешней авторизации EleWise.ELMA.Security.IExternalMembershipService.
Таким образом код, отвечающий за проверку пользователя следует перенести из метода void Validating(UserValidationContext context) в bool ValidateUser(string userNameOrEmail, string password). При этом следует учитывать, что метод ValidateUser не требует проверки AuthProviderGuid пользователя. Возвращаемое методом значение bool будет означать, пройдена ли проверка или нет.
Пример переноса кода:
Старая версия реализации IExternalMembershipService
[Component]
public class LdapExternalMembershipService : IExternalMembershipService
{
...
public bool ValidateUser(string userNameOrEmail, string password)
{
return false;
}
...
}
Старая версия реализации IMembershipServiceEventHandler
[Component]
internal class LdapUserModelMembershipEventHandler : IMembershipServiceEventHandler2
{
...
public void Validating(UserValidationContext context)
{
var lLdapExternalMembershipService = Locator.GetServiceNotNull<LdapExternalMembershipService>();
if (context.User.AuthProviderGuid == lLdapExternalMembershipService.ServiceUid)
{
if (context.Authorized) return;
//попытка авторизации по DN
try
{
if (!ValidatingDN(context))
{
context.Error = new Exception(SR.T("Ошибка авторизации по DN"));
return;
}
}
catch (Exception ex1)
{
//попытка авторизации по шаблону
try
{
if (!ValidatingTemplate(context))
{
context.Error = new Exception(SR.T("Ошибка авторизации по шаблону"));
return;
}
}
catch (Exception ex2)
{
context.Error = ex2;
context.Authorized = false;
Logger.Log.Error(string.Format("LDAP DN fail. Login: {0}. {1}", context.User.UserName, ex1.Message), ex1);
Logger.Log.Error(string.Format("LDAP Template fail. Login: {0}. {1}", context.User.UserName, ex2.Message), ex2);
return;
}
}
context.Authorized = true;
}
}
...
}
Новая версия реализации IExternalMembershipService
[Component]
internal class LdapUserModelMembershipEventHandler : IMembershipServiceEventHandler2
{
...
public void Validating(UserValidationContext context)
{
var lLdapExternalMembershipService = Locator.GetServiceNotNull<LdapExternalMembershipService>();
if (context.User.AuthProviderGuid == lLdapExternalMembershipService.ServiceUid)
{
if (context.Authorized) return;
//попытка авторизации по DN
try
{
if (!ValidatingDN(context))
{
context.Error = new Exception(SR.T("Ошибка авторизации по DN"));
return;
}
}
catch (Exception ex1)
{
//попытка авторизации по шаблону
try
{
if (!ValidatingTemplate(context))
{
context.Error = new Exception(SR.T("Ошибка авторизации по шаблону"));
return;
}
}
catch (Exception ex2)
{
context.Error = ex2;
context.Authorized = false;
Logger.Log.Error(string.Format("LDAP DN fail. Login: {0}. {1}", context.User.UserName, ex1.Message), ex1);
Logger.Log.Error(string.Format("LDAP Template fail. Login: {0}. {1}", context.User.UserName, ex2.Message), ex2);
return;
}
}
context.Authorized = true;
}
}
...
}
Новая версия реализации IMembershipServiceEventHandler
[Component]
internal class LdapUserModelMembershipEventHandler : IMembershipServiceEventHandler2
{
...
public void Validating(UserValidationContext context)
{
}
...
}
4. Устаревшие классы и интерфейсы
Устаревшими объявлен класс EleWise.ELMA.Security.MembershipSettings. Следует воздержаться от его использования где-либо, кроме мест, необходимых для реализации интерфейса EleWise.ELMA.Security.IExternalMembershipService. В ближайших версиях ELMA он будет удален.
Устаревшим объявлена точка расширения реализации внешней авторизации EleWise.ELMA.Security.IExternalMembershipService, являющаяся базовым интерфейсом провайдеров авторизации. В ближайших версиях ELMA она будет удалена, поэтому при наличии собственных провайдеров авторизации следует заранее подготовиться к переносу логики их работы в модули авторизации.