пятница, 9 июля 2010 г.

WCF. Custom windows autentication

Недавно столкнулся со следующей задачей: сервис должен аутентифицировать Windows пользователя с учетом списка пользователей прикладного приложения, сохраненного в базе. Простого решения не нашел, поскольку точки расшинрения WCF позволяют подвязывать Custom аутентификацию только к аутентификацию по паролю, поэтому появилось такое решение.

Создаем провайдер аутентификации.

public class AutenticationManager : ServiceAuthenticationManager

{

public override ReadOnlyCollection<IAuthorizationPolicy> Authenticate(ReadOnlyCollection<System.IdentityModel.Policy.IAuthorizationPolicy> authPolicy,

Uri listenUri,

ref System.ServiceModel.Channels.Message message)

{

// autenticate base.

ReadOnlyCollection<IAuthorizationPolicy> res = base .Authenticate(authPolicy, listenUri, ref message);

// custom autentication.

User user = DataSession.GetUserByName(ServiceSecurityContext.Current.PrimaryIdentity.Name);

if (user != null )

// return base autentication.

return res;

else

// return none autentication.

return null ;

}

}

 

Затем подвешиваем его при помощи атрибута или конфигурации. С помощью атрибута можно сделать так:

[AttributeUsage(AttributeTargets.Class)]

public class AutenticationBehaviorAttribute : Attribute, IServiceBehavior

{

#region IServiceBehavior Members

public void AddBindingParameters(ServiceDescription serviceDescription,

System.ServiceModel.ServiceHostBase serviceHostBase,

System.Collections.ObjectModel.Collection <ServiceEndpoint> endpoints,

System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { }

 

public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)

{

serviceHostBase.Authentication.ServiceAuthenticationManager = new AutenticationManager();

}

 

public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) { }

#endregion

}

 

При помощи конфигурации не подвешивал, но думаю это достаточно просто (лень искать), да и нескольк небезопасно на мой взгляд, поскольку это всеже проверка аутентификации и подмена конфигарации ее может отрубить, а вот отменить конфигурирование в коде достаточно проблематично для администратора сервиса.

Далее навешиваем этот аттрибут на реализацию сервиса:

[AutenticationBehavior()]

public class DataService : IDataService

{

}

В итоге, если пользователь не аутентифицирован вашим кодом, то на клиент уходит сообщение с ошибкой «The Caller was not authenticated by the service».

Информации о менеджере аутентификации к сожалению достаточно мало и как с ним работать пока непонятно до конца. Например непонятно какой результат должен быть у метода Autenticate, если аутентификация не прошла. В принципе нормально отрабатываются ситуации с ошибками, однако это не очень хороший вариант. А при передаче на выход пустой коллекции пользователь считается аутентифицированным.

Если у кого то есть соображения какие значения должен возвращать менеджер или ктото знает способ проверки Windows пользователей лучше и/или правильней – вэлкам. 

 

Posted via email from Комуникликабельность

Комментариев нет: