Аутентификация в службе WCF не поддерживается с помощью SetAuthCookie и полного клиента .net, но работает с silverlight

Я настроил сайт с аутентификацией форм и включенным AspNetCompatibility. Фактический клиент представляет собой приложение Silverlight и работает нормально, однако я хочу отдельно протестировать приложение, используя обычный .net для выполнения службы (живая система для методов без побочных эффектов). Однако, когда я перестаю использовать Silverlight и начинаю использовать полный .net, он не остается аутентифицированным.

В веб-сервисе у меня есть:

[OperationContract]
public bool Login(string Username, string Password, bool isPersistent)
{
    if (Membership.ValidateUser(Username, Password))
    {
        FormsAuthentication.SetAuthCookie(Username, isPersistent);
        return true;
    }
    else
    {
        return false;
    }
}

[OperationContract]
public bool IsLoggedIn()
{
    return HttpContext.Current.User.Identity.IsAuthenticated;
}

Затем в тестовом методе на клиенте я вызываю его так:

Assert.IsTrue(Client.Login("MyUsername","MyPassword", true));
Assert.IsTrue(Client.IsLoggedIn());

Клиент является экземпляром автоматически созданного клиента ServiceReference для .net. Первое утверждение проходит, но второе не проходит, т. е. от одного вызова метода к другому он перестает регистрироваться. Аналогичный метод в приложении silverlight будет проходить.

Как я могу заставить нормальный .net вести себя правильно, как Silverlight? Есть ли лучший способ настройки клиента/сервиса для полного .net?

Запрошена дополнительная информация

Конфигурация службы:

<services>
  <service behaviorConfiguration="MyBehaviour" name="SSCCMembership.Web.Services.LoginService">
    <endpoint address="" binding="customBinding" bindingConfiguration="customBindingBinary"
      contract="SSCCMembership.Web.Services.LoginService" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>
<bindings>
  <customBinding>
    <binding name="customBindingBinary">
      <binaryMessageEncoding />
      <httpTransport />
    </binding>
  </customBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior name="MyBehaviour">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

Конфигурация аутентификации:

<authentication mode="Forms" />
<membership defaultProvider="OdbcProvider">
  <providers>
    <clear />
    <add name="OdbcProvider" type="SSCCMembership.Web.SimpleMembershipProvider" applicationName="/SSCCMembership" requiresUniqueEmail="false" connectionStringName="mainConn" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" writeExceptionsToEventLog="true" />
  </providers>
</membership>

Затем я использую следующее для создания клиента в WPF

public static T LoadService<T>(string URI, Func<CustomBinding, EndpointAddress, T> F)
{
    try
    {
        Uri U = new Uri(new Uri(Root), URI);

        BinaryMessageEncodingBindingElement binary = new BinaryMessageEncodingBindingElement();
        HttpTransportBindingElement transport;
        if (U.Scheme == "http")
            transport = new HttpTransportBindingElement();
        else if (U.Scheme == "https")
            transport = new HttpsTransportBindingElement();
        else
            throw new Exception(U.Scheme + " is not a recognised URI scheme");
        transport.MaxBufferSize = int.MaxValue;
        transport.MaxReceivedMessageSize = transport.MaxBufferSize;
        transport.AllowCookies = true;

        CustomBinding binding;
        binding = new CustomBinding(binary, transport);


        EndpointAddress address = new EndpointAddress(U);

        return F(binding, address);
    }
    catch (Exception)
    {
        return default(T);
    }
}

Который я называю так:

var Client = LoadService(ServiceLocation, (b,e)=>new LoginServiceClient(b,e));

person ForbesLindesay    schedule 23.09.2011    source источник
comment
Ваша привязка настроена на разрешение файлов cookie?   -  person RoccoC5    schedule 23.09.2011
comment
@RoccoC5 Моя привязка создается с использованием «нового CustomBinding (new BinaryMessageEncodingBindingElement (), new HttpTransportBindingElement ())». Как настроить его для включения файлов cookie?   -  person ForbesLindesay    schedule 23.09.2011
comment
@ RoccoC5 Я попробовал new CustomBinding(new BinaryMessageEncodingBindingElement(), new HttpTransportBindingElement(){ AllowCookies=true }), но, похоже, это не имеет никакого значения.   -  person ForbesLindesay    schedule 23.09.2011
comment
Вы можете опубликовать файлы конфигурации сервера и клиента?   -  person Vitalik    schedule 27.09.2011
comment
Для полноты картины, а также поскольку это очень важная часть, не могли бы вы также опубликовать свою конфигурацию FormsAuthentication (/configuration/system.web/authentication/forms), пожалуйста?   -  person mthierba    schedule 27.09.2011
comment
Как вы размещаете службу в тестовом контексте? Мне очень трудно воспроизвести описанный вами сценарий сбоя - что бы я ни делал до сих пор, это всегда работало правильно (т. Е. Клиент оставался в системе, учитывая, что для AllowCookies было установлено значение true).   -  person mthierba    schedule 27.09.2011
comment
Я разместил его на виртуальном хостинге Windows 1 и 1, позже я попробую его на локальном сервере разработки, 1 и 1 могут быть немного мусорными с некоторыми вещами (я думаю перенести его на размещение на Azure)   -  person ForbesLindesay    schedule 28.09.2011


Ответы (3)


Я думаю, что основная проблема, с которой вы сталкиваетесь, связана с контекстом, в котором работает каждое приложение.

Приложение Silverlight запускается в контексте веб-страницы, на которой оно размещено, и, таким образом, может поддерживать информацию о сеансе, файлы cookie и другие виды вещей, о которых вам не нужно беспокоиться вручную.

Как только вы подключаетесь к приложению, работающему вне браузера, ваш контекст (насколько это касается asp.net) меняется. Пробовали ли вы включить/установить приложение Silverlight вне браузера, чтобы увидеть, есть ли у вас такие же ошибки?

Один из способов обойти это — использовать проект Silverlight Unit Test и подключить его к веб-службе для тестирования. (Я успешно сделал это с корпоративными приложениями Silverlight для компании, в которой я работаю) Результатом проекта модульного тестирования Silverlight является приложение Silverlight, которое можно разместить на веб-странице и запускать оттуда — в том же контексте, что и любое другое приложение Silverlight. , что касается ASP.net, что снижает вероятность сбоя вызовов веб-службы из-за контекста.

Посетите главную страницу Silverlight Unit Test Famework, чтобы получить дополнительную информацию...

person EtherDragon    schedule 26.09.2011
comment
+1 Он отлично работает из браузера, хотя я подозреваю, что вы правы. Раньше я проводил модульное тестирование Silverlight, и это, безусловно, был бы запасной вариант, мне просто нужна правильная интеграция с Visual Studio/tfs и т. д. - person ForbesLindesay; 27.09.2011
comment
Да, это один из недостатков Silverlight Test Framework, его нельзя интегрировать в TFS. - person EtherDragon; 27.09.2011
comment
С другой стороны, было намного проще понять, когда я впервые учился использовать модульные тесты :) - person ForbesLindesay; 27.09.2011

Измените метод IsLoggedIn(), чтобы он ссылался на ServiceSecurityContext вместо HttpContext:

[OperationContract]
public bool IsLoggedIn()
{
    return ServiceSecurityContext.Current.PrimaryIdentity.IsAuthenticated;
}
person RoccoC5    schedule 23.09.2011
comment
Это не имело никакого значения - person ForbesLindesay; 23.09.2011

У меня была такая же проблема, и в итоге я просто реализовал службы аутентификации WCF... Документация была простой и отлично работала с поставщиком аутентификации форм ASP.NET.
http://msdn.microsoft.com/en-us/library/bb386582.aspx

person Nick Nieslanik    schedule 23.09.2011
comment
По какой-то причине возникают проблемы, когда я пытаюсь использовать это с моим веб-хостом. В любом случае, тот факт, что он работает для Silverlight, означает, что с этим можно справиться, просто изменив клиент (что я бы предпочел) - person ForbesLindesay; 23.09.2011