开发者

Authentication to a WCF service not maintained using SetAuthCookie and a full .net client but works with silverlight

开发者 https://www.devze.com 2023-04-07 01:32 出处:网络
I\'ve setup a site with forms authentication and AspNetCompatibility enabled.The actual client is a silverlight application, and works fine, however I want to unit test the application separately usin

I've setup a site with forms authentication and AspNetCompatibility enabled. The actual client is a silverlight application, and works fine, however I want to unit test the application separately using normal .net to exercise the service (live system for methods without side-effects). However, when I stop using Silverlight and start using full .net it doesn't remain authenticated

In a web service I have:

[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;
}

Then in a test method on the client I call it like so:

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

The client is an instance of the automatically generated ServiceReference client for .net. The first assertion passes but the second one fails, i.e. from one method call to the next it stops being logged in. A similar method in the silverlight application would pass.

How can I make normal .net behave correctly as silverlight would? Is there just a better way of configuring client/service for full .net?

Aditional Info Requested

Service Config:

<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 Config:

<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>

I then use the following to construct the client in 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);
    }
}

Which I call like:

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


I think the main problem you are having is due to the context that each application runs in.

A Silverlight application runs in the context of the web-page it's hosted in - and thus, can maintain session info, cookies, and all sorts of other things that you don't need to manually worry about.

As soon as you connect with an application running outside of the browser, your context (as far as asp.net is concerned) has changed. Have you tried enabling/installing the silverlight application out-of-browser to see if you have the same errors?

One way to work around this is to use the Silverlight Unit Test project and connect that to your web service for testing. (I have successfully done this with enterprise silverlight apps for the company I work for) The silverlight unit test project results in a silverlight app that can be hosted on a web page, and run from there - in the same context as any other silverlight app, as far as ASP.net is concerned, making your web-service calls much less likely to fail due to context.

Check out the Silverlight Unit Test Famework Homepage for more info...


Change your IsLoggedIn() method to reference the ServiceSecurityContext instead of HttpContext:

[OperationContract]
public bool IsLoggedIn()
{
    return ServiceSecurityContext.Current.PrimaryIdentity.IsAuthenticated;
}


I had this same type of problem and ended up just implementing the WCF Authentication Services... The documentation was straight forward and it works great with the ASP.NET forms auth provider.
http://msdn.microsoft.com/en-us/library/bb386582.aspx

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号