Вопрос

Я разрабатываю сервисы WCF с Базовая привязка HttpBinding, эти службы должны быть доступны с использованием .net 1.1 и .net 2.0, для этой цели я использую Базовая привязка HttpBinding.
В старых веб-сервисах ASMX я использовал один заголовок Soap (AuthHeader) для аутентификации пользователя при каждом запросе.

Как я могу пройти аутентификацию в WCF, используя Базовая привязка HttpBinding? Любой образец или учебное пособие будут полезны.


nRk

Это было полезно?

Решение

Вы можете использовать AuthHeader, как вы делали до перехода на WCF.Возможно, это будет более удобно для вас, потому что принципы останутся прежними.Плохая вещь, которую я вижу в этом решении, - это передача пароля простым текстом.В любом случае, это просто еще один вариант, и вы можете каким-то образом зашифровать / расшифровать пароль.

В этом случае вы должны реализовать свой собственный IDispatchMessageInspector & IClientMessageInspector, например

[AttributeUsage(AttributeTargets.Class)]
public class CredentialsExtractorBehaviorAttribute : Attribute, IContractBehavior, IDispatchMessageInspector
{
    #region IContractBehavior implementation.

    public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint,
                                      DispatchRuntime dispatchRuntime)
    {
        dispatchRuntime.MessageInspectors.Add(this);
    }

    ... empty interface methods impl skipped ...

    #endregion

    #region IDispatchMessageInspector implementation.

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        int i = request.Headers.FindHeader("username", "sec");
        if (-1 != i)
        {
            string username = request.Headers.GetHeader<string>("username", "sec");
            ... do smth ...
        }
        return null;
    }

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
        return;
    }

    #endregion
}

В примере я поместил в заголовок только username , но вы можете реализовать свой класс a, содержащий username и password, и использовать его вместо string .На клиенте:

internal class CredentialsInserter : IContractBehavior, IClientMessageInspector
{
    private string m_username;

    public CredentialsInserter(string username)
    {
        m_username = username;
    }

    #region IContractBehavior implementation.

    ... empty interface methods impl skipped ...

    public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint,
                                    ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(this);
    }

    #endregion

    #region IClientMessageInspector implementation.

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        MessageHeader<string> mh = new MessageHeader<string>(m_username);
        request.Headers.Add(mh.GetUntypedHeader("username", "sec"));
        return null;
    }

    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        return;
    }

    #endregion
}

Затем вам следует поместить атрибут CredentialsExtractorBehaviorAttribute в ваш класс реализации сервиса.

[CredentialsExtractorBehavior]
public class DummyService : IDummyService
{
   ... impl ...
}

И на стороне клиента вы должны сделать следующее:

        using (DummyServiceClient c = new DummyServiceClient("TcpEndpoint"))
        {
            c.ChannelFactory.Endpoint.Contract.Behaviors.Add(
                new CredentialsInserter("_username_"));
            c.DummyMethod();
        }

Другие советы

Прежде всего - да, вы можете!Это зависит от того, используете ли вы Транспорт или привязку к сообщениям - если вы подключены к Интернету, вы, скорее всего, используете защиту на основе сообщений.

К сожалению, для безопасности на основе сообщений BasicHttpBinding поддерживает только сертификаты, что является небольшой проблемой.

С другой стороны, wsHttpBinding также будет поддерживать имя пользователя / пароль или другие методы.

Вы бы настроили wsHttpBinding с учетными данными клиента username / password поверх безопасности на основе сообщений следующим образом:

  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="wsUserName">
          <security mode="Message">
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service name="yourservice">
        <endpoint name="YourEndpoint"
                  address=""
                  binding="wsHttpBinding"
                  bindingConfiguration="wsUserName"
                  contract="IYourService" />
      </service>
    </services>
  </system.serviceModel>

Раздел под <bindings> определяет конфигурация привязки для wsHttpBinding, который использует защиту сообщений с учетными данными клиента имени пользователя / пароля.

Раздел под <service> определяет пример сервиса, который использует wsHttpBinding и который ссылается на ту конфигурацию привязки, которую мы только что определили.

На стороне сервера, теперь вы можете использовать имя пользователя/пароль, которые пересылаются по сети для проверки звонящих в активный каталог (каждый вызов должен объявлений с вами счет), или в систему базы данных членства ASP.NET ;или, если вам действительно очень нужно, вы также могли бы написать свой собственный механизм аутентификации.

Найдите много полезной информации о WCF безопасность в Codeplex - отличный ресурс.

Проверьте сценарии здесь попытаться подобрать один из них к вашей ситуации.Каждый сценарий снабжен контрольным списком элементов, необходимых для реализации решения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top