0

Я внедрил пользовательскую аутентификацию с помощью UserNamePasswordValidator.Ошибка аутентификации WCF

В соответствии с требованием к проекту мне требуется четыре входных параметра для аутентификации (Username, Password, SiteID, BrandID).

Но Validate метод принимает только два параметра: Validate (строка, строка имя пользователя пароль)

Вопрос:

1) Как я могу отправить более чем два параметра Проверка метода?

2) Есть ли другой подход для определения аутентификации WCF с помощью собственных методов проверки подлинности?

Спасибо,

Ram

+0

Я отредактировал мое сообщение, чтобы показать вам код OperationContext/GenericContext . Надеюсь, это полезно –

ответ

0

1. Базовое решение с конкатенации

Может быть самый быстрый способ и самый простой CONCATENATE Имя пользователя, SiteID и BrandID (разделенных/или - и сделать какие-то escape-последовательности, чтобы предотвратить использование разделительных символов) в заголовке Username и создать CustomValidator.

--------------------------- Редактировать ---------------- -----------

2. Есть несколько способов, чтобы пройти некоторые ** дополнительные заголовки, и использовать OperationContext. **

Я также покажу, как поставить декларативные разрешения

Для этого вы можете использовать классы Juval Löwy. Он реализует GenericContext<T>, который вы можете использовать.

GenericContext<T> инкапсулирует механику доступа к заголовкам.

2,1 Создание общей библиотеки

Чтобы разделить некоторые данные от клиента и сервера, передаются как мыльные заголовки

[DataContract] 
public class ExtraHeaders 
{ 
    [DataMember] 
    public String Username { get; set; } 
    [DataMember] 
    public String Password { get; set; } 
    [DataMember] 
    public String BranchId { get; set; } 
    [DataMember] 
    public String SiteId { get; set; } 
} 

2,2 На стороне клиента

Проходят дополнительные заголовки :

static void Main(string[] args) 
{ 
// provide identity as headers 
    var extraHeaders = new ExtraHeaders 
    { 
     Username="manager", 
     Password= "password", 
     BranchId = "Branch2", 
     SiteId = "Site2" 
    }; 
    MyContractClient proxy = new MyContractClient(extraHeaders); 

    proxy.MyMethod(); 

    proxy.Close(); 
} 

Прокси-сервер должен быть изменен немного (не Visual Studio или svcutil.exe поколения):

class MyContractClient : HeaderClientBase<IMyContract, ExtraHeaders>, IMyContract 
{ 
    public MyContractClient(string key,string value) : base(key,value) 
    {} 
    public void MyMethod() 
    { 
     Channel.MyMethod(); 
    } 
} 

2.3 - Добавление декларативного разрешения на стороне сервера

декларативного разрешения с
[PrincipalPermission(SecurityAction.Demand, Role = "Manager")]

class MyService : IMyContract 
{ 
    [PrincipalPermission(SecurityAction.Demand, Role = "Manager")] 
    public void MyMethod() 
    { 
     var extraHeaders = ExtraHeadersContext.Current; 
     if (extraHeaders != null) 
     { 
      //Console.WriteLine("Extra headers: (BranchId:{0}, SiteId:{1}) ", extraHeaders.BranchId, extraHeaders.SiteId); 
      Console.WriteLine("Service call from : {{{0}}}", extraHeaders.Username); 
     } 
    } 
} 

2.4 Добавить serviceAuthorizationBehavior придерживаться идентичности к использованию

<behaviors> 
    <serviceBehaviors> 
    <behavior name="customIdentificationBehavior"> 
     <serviceAuthorization principalPermissionMode="Custom"> 
     <authorizationPolicies> 
      <add policyType="Security.HttpContextPrincipalPolicy,Host" /> 
     </authorizationPolicies> 
     </serviceAuthorization> 
    </behavior> 

2.5 Внедрение услугиAuthorizationBehvior

Целью этого поведения является назначение принципала и идентификатора вызывающему.

namespace Security 
{ 
    public class HttpContextPrincipalPolicy : IAuthorizationPolicy 
    { 
     public bool Evaluate(EvaluationContext evaluationContext, ref object state) 
     { 
      try 
      { 
       var extraHeaders = ExtraHeadersContext.Current; 
       if (extraHeaders != null) 
       { 
        IPrincipal principal = new CustomPrincipal(
         new GenericIdentity(extraHeaders.Username, "Custom Provider"),extraHeaders); 

        evaluationContext.Properties["Principal"] = principal; 
        // Put user here so it can be used for declarative access on methods 
        evaluationContext.Properties["Identities"] = new List<IIdentity>() { principal.Identity }; 
       } 
       else 
       { 
        SetAnonymousPrincipal(evaluationContext); 
       } 
      } 
      catch (Exception) 
      { 
       SetAnonymousPrincipal(evaluationContext); 
      } 
      return true; 
     } 
    } 
} 

2,6 Класс CustomPrincipal заботится сдачи пользователю в роли

public class CustomPrincipal : IPrincipal 
{ 
    private ExtraHeaders headers; 
    private IIdentity identity; 

    public CustomPrincipal(IIdentity identity, ExtraHeaders headers = null) 
    { 
     this.identity = identity; 
     this.headers = headers; 
    } 
    public IIdentity Identity 
    { 
     get { return identity; } 
    } 
    public bool IsInRole(string role) 
    { 
     String[] roles; 
     if (identity.Name == "manager") 
      roles = new string[1] { "Manager" }; 
     else 
      roles = new string[1] { "User" }; 
     return roles.Contains(role); 
    } 
} 

Заключение

За кулисами, классы Юваль читать (на стороне сервера) и запись (клиентская сторона).

Отрывок, например:

 if(OperationContext.Current.IncomingMessageProperties.ContainsKey(ContextMessageProperty.Name)) 
    { 
     ContextMessageProperty contextProperty = OperationContext.Current.IncomingMessageProperties[ContextMessageProperty.Name] as ContextMessageProperty; 
     if(contextProperty.Context.ContainsKey(key) == false) 
     { 
      return null; 
     } 
     return contextProperty.Context[key]; 
    } 

Ссылка на полный рабочий исходный код: http://1drv.ms/1OqPMUM

Ссылка Отлично Джувал Лоуи в: Посмотрите на «Контекст привязок как пользовательский контекст» на странице http://www.idesign.net/Downloads к имеют класс GenericContext Его книга замечательная, если вы проводите время на WCF

С уважением

+0

Спасибо. Пойдет с конкатенацией переменных. – ram

+0

Хорошо. Поэтому я также попробовал другой путь. Повторяемый CustomValidator. Реализован OperationContext и передан переменные в дополнительном заголовке. Но как я могу связать информацию о пользователе с текущим запросом. Как я могу реализовать Custom Principal и Identity таким образом. – ram

+0

Согласно Löwy, вы можете перейти к GenericContext любому T, который является DataContract –

Смежные вопросы