Calling WCF secured service from Java
Calling WCF secured service from Java
recently I was working on exposing secured WCF service
to Java consumers.
I was responsible for the .NET side and a java expert named Tsvika
responsible for the Java side.
enabling secured conversation between Java and .NET using WCF is not a trivial task,
and it does needed some additional steps.
you should have certificate install, and having the binding and behaviors configured
in a way that the Java proxy can manage.
Certificates
the first step needed is having a valid certificate.
the certificate should be installed into the service's hosting machine.
you can learn more on how to handle the certificates in here.
Service configuration
Binding
the secure binding should look as follow
Code Snippet
- <wsHttpBinding>
- <binding name="UsernameAndPassword">
- <security mode="Message">
- <message clientCredentialType="UserName"
- negotiateServiceCredential="false"
- establishSecurityContext="false"
- algorithmSuite="Basic128"/>
- </security>
- </binding>
- </wsHttpBinding>
line 3, the binding mode should be Message
line 4, the client certificate type should be UserName.
line 5, the negotiation service credentials must switch off.
line 6, the establish security context should also turn off.
Behaviors
use the following behaviors
Code Snippet
- <serviceBehaviors>
- <behavior name="Bnaya.Samples.UsernameAndPassword">
- <serviceMetadata httpGetEnabled="true" policyVersion="Default" />
- <serviceCredentials>
- <serviceCertificate findValue="RPKey" storeLocation="LocalMachine"
- storeName="TrustedPeople" x509FindType="FindBySubjectName" />
- <userNameAuthentication userNamePasswordValidationMode="Custom"
- customUserNamePasswordValidatorType="Bnaya.Samples.MyUserNameValidator, WcfSecureed" />
- </serviceCredentials>
- </behavior>
- </serviceBehaviors>
lines 5-6, define which certificate should use for the service (RPKey is the name of the certificate).
in case of service hosting it is more reasonable to install the certificate on the machine level (instead of the user level) .
lines 7-8, define the authentication handler (as you can see in the following snippet).
Code Snippet
- public sealed class MyUserNameValidator : UserNamePasswordValidator
- {
- public override void Validate(string userName, string password)
- {
- if (userName != "admin" || password !="admin")
- throw new SecurityException("Access denied.");
- }
- }
the validate method is where your authentication code goes.
End point
nothing is special about the definition of the service section
Code Snippet
- <service name="Bnaya.Samples.Service1" behaviorConfiguration="Bnaya.Samples.UsernameAndPassword">
- <host>
- <baseAddresses>
- <add baseAddress="http://localhost:8731/Service1/"/>
- </baseAddresses>
- </host>
- <endpoint address="" binding="wsHttpBinding" contract="Bnaya.Samples.IService1"
- bindingConfiguration="UsernameAndPassword">
- <identity>
- <dns value="localhost"/>
- </identity>
- </endpoint>
- </service>
small tip: replace the localhost with the correct IP so when the Java proxy is generated,
the endpoint will be correct.
Java
java has several libraries that can invoke WCF, unfortunately not all of them
has good implementation for the WCF secured conversation.
the library that do working fine with secured conversation is Sun: Metro Web Services
and more precisely you should use WSIT.
do not waste your time on Axis2 / Rampart it is only half backed in compare to the Sun library.
Summary
this task is not travel, but with the right library and java expert like Yaakov,
it is certainly feasible.
תגים של Technorati:
WCF,
Java