Page 1 of 1
WebService C#
Posted: Mon Mar 04, 2013 4:59 pm
by tbertrand
Hi everybody,
I'm trying to create a client in C# to use openemm's webservice.
I'm new in webservices and C# and I would like to know how to put the Soap Header with wsse security using the provided wsdl for API 2.0.
I can use the wsdl for API 1, but I'm not able to get through the authentication.
Everytime I connect to openemm, I receive this error :
"Message does not conform to configured policy [ AuthenticationTokenPolicy(S) ]: No Security Header found;"
If somebody used C#, some tips would be very helpfull
Thank you in advance !
T. Bertrand
Re: WebService C#
Posted: Thu Mar 07, 2013 3:29 pm
by pixus
I just got it!
I made in this way:
PS: WCFemmService is the .cs I generated with the svcutil.exe of Visual Studio.
Be careful, in the generated cs file, you have to modify "changeDateField" and "creationDateField" from Datetime to string (if I didn't, i had problems with method GetSubscriberBinding )
Code: Select all
string username = "MYUSN";
string password = "MYPWD";
ChannelFactory<WCFemmService> channelFactory;
EndpointAddress serviceAddress = new EndpointAddress("http://www.mywebsite.it:8080/openemm-ws2/");
CustomBinding binding = new CustomBinding();
var security = TransportSecurityBindingElement.CreateUserNameOverTransportBindingElement();
security.AllowInsecureTransport = true;
security.IncludeTimestamp = false;
security.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256;
security.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
var encoding = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
var transport = new HttpTransportBindingElement();
transport.MaxReceivedMessageSize = 20000000; // 20 megs
// DECOMMENTARE LE SEGUENTI 2 RIGHE PER PASSARE PER FIDDLER
//transport.ProxyAddress = new Uri("http://localhost:8888");
//transport.UseDefaultWebProxy = false;
binding.Elements.Add(security);
binding.Elements.Add(encoding);
binding.Elements.Add(transport);
channelFactory = new ChannelFactory<WCFemmService>(binding, serviceAddress);
channelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
channelFactory.Endpoint.Behaviors.Add(new CustomCredentials());
channelFactory.Credentials.UserName.UserName = username;
channelFactory.Credentials.UserName.Password = password;
WCFemmService oemmClient;
oemmClient = channelFactory.CreateChannel();
Using these other classes
Code: Select all
public class CustomCredentials : ClientCredentials
{
public CustomCredentials()
{ }
protected CustomCredentials(CustomCredentials cc)
: base(cc)
{
}
public override System.IdentityModel.Selectors.SecurityTokenManager CreateSecurityTokenManager()
{
return new CustomSecurityTokenManager(this);
}
protected override ClientCredentials CloneCore()
{
return new CustomCredentials(this);
}
}
internal class CustomSecurityTokenManager : ClientCredentialsSecurityTokenManager
{
public CustomSecurityTokenManager(CustomCredentials cred)
: base(cred)
{
}
public override System.IdentityModel.Selectors.SecurityTokenSerializer CreateSecurityTokenSerializer(System.IdentityModel.Selectors.SecurityTokenVersion version)
{
return new CustomTokenSerializer(System.ServiceModel.Security.SecurityVersion.WSSecurity11);
}
}
internal class CustomTokenSerializer : WSSecurityTokenSerializer
{
public CustomTokenSerializer(SecurityVersion sv)
: base(sv)
{
}
protected override void WriteTokenCore(System.Xml.XmlWriter writer, System.IdentityModel.Tokens.SecurityToken token)
{
string usn = "MYUSN";
string pwd = "MYPWD";
const string tokennamespace = "o";
DateTime created = DateTime.Now.ToUniversalTime();
var nonce = getNonce();
string nonceToSend = Convert.ToBase64String(Encoding.UTF8.GetBytes(nonce));
string createdStr = created.ToString("yyyy-MM-ddTHH:mm:ssZ");
//string dec = base64Decode(nonce);
string passwordToSend = GetSHA1String(nonce + createdStr + pwd);
System.IdentityModel.Tokens.UserNameSecurityToken unToken = (System.IdentityModel.Tokens.UserNameSecurityToken)token;
writer.WriteRaw(String.Format(
"<{0}:UsernameToken xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">" +
"<{0}:Username>" + usn + "</{0}:Username>" +
"<{0}:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest\">" +
passwordToSend + "</{0}:Password>" +
"<{0}:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" +
nonceToSend + "</{0}:Nonce>" +
"<wsu:Created>" + createdStr + "</wsu:Created></{0}:UsernameToken>", tokennamespace));
}
protected string getNonce()
{
string phrase = Guid.NewGuid().ToString();
return phrase;
}
protected string GetSHA1String(string phrase)
{
SHA1CryptoServiceProvider sha1Hasher = new SHA1CryptoServiceProvider();
byte[] hashedDataBytes = sha1Hasher.ComputeHash(Encoding.UTF8.GetBytes(phrase));
string test = Convert.ToString(hashedDataBytes);
return Convert.ToBase64String(hashedDataBytes);
}
}
I tried with a FindSubscriber and a GetSubscriber and it works.
However I still can use AddSubscriber : for this function I use webservice 1.0
Re: WebService C#
Posted: Mon Mar 25, 2013 12:04 pm
by tbertrand
Thank you very much !
But I still have an error.
When I try to get a response (for every type of request) I get this error :
Code: Select all
nested exception is com.sun.xml.wss.XWSSecurityException: com.sun.xml.wss.impl.WssSoapFaultException: Authentication of Username Password Token Failed
The username/password for
channelFactory.Credentials.UserName.UserName and
WriteTokenCore are the same ?
My sample code for request/response just after
oemmClient = channelFactory.CreateChannel(); is :
Code: Select all
AddMailinglistRequest admlr = new AddMailinglistRequest();
admlr.description = "premier TEST de Mailing par ws MDF";
admlr.shortname = "ZZZ TestMDF";
AddMailinglistRequest1 admlr1 = new AddMailinglistRequest1();
admlr1.AddMailinglistRequest = admlr;
AddMailinglistResponse1 resp1 = oemmClient.AddMailinglist(admlr1);
AddMailinglistResponse resp = resp1.AddMailinglistResponse;
int i = resp.mailinglistID;
and the error is on :
Code: Select all
AddMailinglistResponse1 resp1 = oemmClient.AddMailinglist(admlr1);
Did you have any ideas ?
Greetings
Re: WebService C#
Posted: Wed Apr 03, 2013 9:11 am
by tbertrand
Ok...my bad. Just forget to add an entry in the table
webservice_user_tbl in my DB for my webservice user ...
So thanks a lot for your code, everythings works perfectly !