Click here to Skip to main content
15,117,719 members
Please Sign up or sign in to vote.
4.75/5 (4 votes)
Hi
(Just a heads up that I have also posted this on the MSDN WCF Forum: http://social.msdn.microsoft.com/Forums/en/wcf/thread/87a254c8-e9d1-4d4c-8f62-54eae497423f)

I will include quite a bit of information in this question. Basically I'm writing a WCF service and separate example .NET and Java clients to access that service. The client is required to connect via HTTPS and provide username/password authentication. The .NET client is not a problem. However I have not been able to get the Java client to work and have attempted various approaches mentioned below. I'm working with Visual Studio 2010 SP1, NetBeans IDE 7.0 (EE edition) and JDK 1.6.0_26 and I've been using the "New->Web Service Client" feature in NetBeans to setup the service reference in all cases. The service and client are running on the same machine with Windows 7 x64 SP1 and IIS 7.
I'd prefere to use wsHttpBinding, basicHttpBinding or the metroBinding (see http://wcf.codeplex.com/releases/view/68276) in that order of preference. Assistance from anyone who has managed to get a Java client to successfully access a WCF service over HTTPS using username/password authentication would be appreciated.

A description of the approaches attempted thus far is as follows:


  1. Using WsHttp or basicHttp, which it appears others have managed to get to work with Java with authentication in some cases, initially yielded SocketException, Connection Reset. After regenerating and importing (into the windows certificate store) the test "CA" and Server certificates, (perhaps the -sky Exchange option was omitted for the server key the first time) the error for using these bindings is: PKIX path building failed...unable to find valid certification path to requested target. Basically unable to validate the certificate.
  2. After getting that, I read up on Keytool and managed to import both the "CA" (in case it's needed) and server certificate (cer files) into a JSK file.
  3. Then when clicking on Edit Web Service Attributes on the reference, I had initially specified the details (tried both the CA alias and the Server alias) under Keystore, realised this was wrong (this seems to be for the client certificate) but could not specifiy the details under Truststore because the button was greyed out.
  4. After that I thought perhaps the web service reference details were not being picked up properly and decided to use the metroBinding. This allows specifying certificate details under Truststore. However it also now results in a "Invalid key provided for encryption/decryption" error, also it's connecting via HTTP and not HTTPS, and not sure how to specify this - HTTPS should be the automatic default because the service requires a username/password. The client was automatically connecting via HTTPS when using WsHttp and BasicHttp.
  5. The service compiles and the start page displays for all the bindings.


In Summary

  1. For basicHttpBinding, without authentication, over HTTP, both the Java and .NET clients work.
  2. For both basicHttpBinding and wsHttpBinding, with autentication and over HTTPS, the .NET client works and I get this error for the Java client: com.sun.xml.ws.client.ClientTransportException: HTTP transport error: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target. This is probably because it was not possible to specify anything in the truststore as it's greyed out on the UI in NetBeans.
  3. For the metroBinding, with the .NET client I get: "The service certificate is not provided for target 'http://myFQDN/TestWcfInteropService/Service.svc'. Specify a service certificate in ClientCredentials." Additionally if I try to change HTTP to HTTPS in the client app.config, I get: "The provided URI scheme 'https' is invalid; expected 'http'." For the Java client I get: "Invalid key provided for encryption/decryption."
    I can include full exception details for a specific scenario if suggested - I didn't for now to keep the question shorter.


    The certificate setup is as follows:
    Configuring Certificates for Windows and IIS (run from a Visual Studio 2010 Command Window):

    1. Run makecert -n "CN=TestCA" -r -sv TestCA.pvk TestCA.cer, Enter "123" for the password (3 times).
    2. Import TestCA.CER into Trusted Root Certification Authorities\Certificates of machine store with certificates MMC.
    3. Use the TestCA certificate to sign a test server certificate by running the following BUT replace myFQDN with your FQDN: makecert -iv TestCA.pvk -n "CN=myFQDN" -ic TestCA.cer -pe -sky exchange -sv TestServer.pvk TestServer.cer, Enter "123" for the password (4 times)
    4. Export PFX file from server private and public certificates: pvk2pfx -pvk TestServer.pvk -spc TestServer.cer -pfx TestServer.pfx -pi 123
    5. Import TestServer.pfx into Personal\Certificates of machine store with certificates MMC. (Need to change file type filter to "Personal Information Exchange" when browsing for the file. Use "123" for the password again.
    6. In IIS manager, click Default Web Site, click Bindings on the right hand side, click HTTPS, click Edit. Select the relevant certificate in the SSL certificate drop down and click Ok, then close.
    7. Ensure certificate is correctly configured by browsing to https://FQDN in Internet Explorer and ensuring the IIS welcome page is displayed without any certificate warnings.


    Configuring JSK File For Java (run from C:\Program Files\Java\jdk1.6.0_26\bin, or wherever JDK bin is installed):

    1. keytool -genkey -alias mydomain -keyalg RSA -keystore keystore.jks -keysize 2048
    2. Enter "123456" for the password (twice).
    3. Keep pushing Enter to accept the defaults until it asks if it's correct, then type "yes" and push enter.
    4. Enter "123456" for the password (twice).
    5. keytool -import -trustcacerts -alias root -file D:\Documents\Work\CertificateStuff\TestCA.cer -keystore keystore.jks [Edit path to TestCA.cer as needed].
    6. Enter "123456" for the password.
    7. Type "yes" and push enter.
    8. keytool -import -trustcacerts -alias myFQDN -file D:\Documents\Work\CertificateStuff\TestServer.cer -keystore keystore.jks [1. Replace myFQDN with you FQDN. 2. Edit path to TestServer.cer as needed.]
    9. Enter "123456" for the password.
    10. Move keystore.jks out of JDK bin folder to a more convenient location.


    The web.config files for the service(s) when using basicHttpBinding and metroBinding are are below. They are done separately to keep the config files simple. I have omitted wsHttpBinding, but it's similar to basicHttpBinding. I can include an example of that as well if it will help, but did not for now to keep the question shorter.

    basicHttpBinding
    <configuration>
    
     <system.web>
      <compilation debug="true" targetframework="4.0" />
      <membership defaultprovider="TestMembershipProvider">
       <providers>
        <add name="TestMembershipProvider" type="WCFInteropService.TestMembershipProvider" />
       </providers>
      </membership>
     </system.web>
     
     <system.servicemodel>
    
      <bindings>
       <basichttpbinding>
        <binding name="BasicServiceBinding">    
         <security mode="TransportWithMessageCredential">
          <transport clientcredentialtype="None" />
          <message clientcredentialtype="UserName" />
         </security>     
        </binding>
       </basichttpbinding>   
      </bindings>
      
      <behaviors>
       <servicebehaviors>
        <behavior name="ServiceBehavior">
         <servicemetadata httpgetenabled="true" />
         <servicedebug includeexceptiondetailinfaults="false" />
         <servicecredentials>
          <usernameauthentication usernamepasswordvalidationmode="MembershipProvider">
           membershipProviderName="TestMembershipProvider" />
         </usernameauthentication></servicecredentials>
        </behavior>
       </servicebehaviors>
      </behaviors>
    
      <services>
       <service behaviorconfiguration="ServiceBehavior" name="TestWcfBasicHttpService.Service">
        <endpoint address="" binding="basicHttpBinding" bindingconfiguration="BasicServiceBinding" contract="TestWcfBasicHttpService.IService">
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
       </service>
      </services>
      
     </system.servicemodel> 
    </configuration>


    metroBinding
    <configuration>
     <system.web>
      <compilation debug="false" targetframework="4.0" />
      <membership defaultprovider="TestMembershipProvider">
       <providers>
        <add name="TestMembershipProvider" type="WCFInteropService.TestMembershipProvider" />
       </providers>
      </membership>
     </system.web>
     <system.servicemodel>
      <services>
       <service name="Service" behaviorconfiguration="ServiceBehavior">
        <!-- Service Endpoints -->
        <endpoint address="" bindingconfiguration="interopBinding" binding="metroBinding" contract="IService">
         <!-- 
           Upon deployment, the following identity element should be removed or replaced to reflect the 
           identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
           automatically.
         -->
         <identity>
          <dns value="localhost" />
         </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
       </service>
      </services>
      <behaviors>
       <servicebehaviors>
        <behavior name="ServiceBehavior">
         <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
         <servicemetadata httpgetenabled="true" />
         <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
         <servicedebug includeexceptiondetailinfaults="false" />
         <!-- To configure the service certificate -->
         <servicecredentials>
          <servicecertificate storelocation="LocalMachine" storename="My" x509findtype="FindBySubjectDistinguishedName" findvalue="CN=myFQDN" />
          <usernameauthentication usernamepasswordvalidationmode="MembershipProvider" membershipprovidername="TestMembershipProvider" />
         </servicecredentials>
        </behavior>
       </servicebehaviors>
      </behaviors>
      <bindings>
       <metrobinding>
        <binding name="interopBinding" messageencoding="Text">
         <security mode="UserNameOverCertificate" establishsecuritycontext="false" algorithmsuite="Default" />
        </binding>
       </metrobinding>
      </bindings>
      <extensions>
       <bindingextensions>
        <add name="metroBinding" type="Microsoft.ServiceModel.Interop.Metro.Configuration.MetroBindingCollectionElement, Microsoft.ServiceModel.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4fc38efee625237e" />
       </bindingextensions>
      </extensions>
     </system.servicemodel>
     <system.webserver>
      <modules runallmanagedmodulesforallrequests="true" />
     </system.webserver>
    </configuration>
Posted
Updated 28-Jun-11 3:24am
v4
Comments
Vivek Krishnamurthy 28-Jun-11 5:30am
   
Very detailed, yet difficult to get to your question...
thatraja 10-Dec-11 22:29pm
   
Agree
Brendon1234 12-Dec-11 15:05pm
   
Thanks for reading/responding. To me the question was obvious, but to confirm - "How do I get this to work?" - together with the steps attempted and the errors/results obtained in each case.
asgv 9-Feb-13 13:53pm
   
Hi Brendon,
I'm running into the same issue with basicHttpBinding and a java client. Were you ever able to figure this out?
Thanks!
Brendon1234 12-Feb-13 16:36pm
   
Unfortunately not - and the work in that area didn't continue, so I didn't get chance to spend much more time on it.

See if this tutorial helps: http://webservices20.blogspot.com.au/2011/06/test-drive-shiny-new-wcf-interop.html[^]

You might also try and contact Yaron as he really knows his way around WCF Interop.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900