开发者

Connecting to SAP Web Service from C# .NET application

开发者 https://www.devze.com 2023-01-15 11:38 出处:网络
I\'ve written a Windows Application to test a connection to a clients SAP web services.The web service call requires X509 certificate security.

I've written a Windows Application to test a connection to a clients SAP web services. The web service call requires X509 certificate security.

After reading various articles on the internet I've come up with three ways to attach the X509 certificate to the web service call. Unfortunately all of these attempts return a '401 Unauthorised Access'. However, I can connect to the web service via the URL in IE.

Does anybody have any sugestions as to what I may be doing wrong? I am using WSE 3.0 and the three methods I am using to attach the certificate are as follows:-

Certificate

X509Certificate2 oCert = GetSecurityCertificate(oCertificate);  
svc.ClientCertificates.Add(oCert);

Token

X509SecurityToken oToken = GetSecurityToken(oCertificate);
svc.RequestSoapContext.Security.Tokens.Add(oToken);

Policy

SAPX509Assertion sapX509Assertion = new SAPX509Assertion(oCertificate, oStoreLocation, oStoreName, oFindType);  
svc.SetPolicy(sapX509Assertion.Policy());

GetSecurityToken() and GetSecuirtyCertificate both search the certificate store. The SAPX509Assertion does this:-

public SAPX509Assertion(String certSubject, StoreLocation oStoreLocation, StoreName oStoreName, X509FindType oFindType)  
{  
    ClientX509TokenProvider = new X509TokenProvider(oStoreLocation,
                                                     oStoreName, certSubject, oFindType);  
    ServiceX509TokenProvider = new X509TokenProvider(oStoreLocation,
                                                     oStoreName, certSubject, oFindType);  

    Protection.Request.EncryptBody = false;  
    Protection.Response.EncryptBody = false;  
} 

Update OK, I have a WCF call now in place. I couldn't use the BasicHttpBinding method shown by Eugarps as it complained that I was connecting to a https address and expected http...which made sense. The code I now have is:-

var binding = new WSHttpBinding();
binding.MaxReceivedMessageSize = int.MaxValue;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
binding.Security.Mode = SecurityMode.Transport;

WCFConnection.CreateAbsenceWSlow.ZWSDHTM_GB_AMS_CREATEABS_lowClient client;
CreateAbsenceWSlow.ZfhhrGbbapiZgeeamsCreateabsResponse response;
CreateAbsenceWSlow.ZfhhrGbbapiZgeeamsCreateabs data;
//Assign address
v开发者_Python百科ar address = new EndpointAddress(sUrl);

//Create service client
client = new CreateAbsenceWSlow.ZWSDHTM_GB_AMS_CREATEABS_lowClient(binding, address);

//Assign credentials
client.ClientCredentials.UserName.UserName = sUserName;
client.ClientCredentials.UserName.Password = sPassword;

response = new CreateAbsenceWSlow.ZfhhrGbbapiZgeeamsCreateabsResponse();
data = new WCFConnection.CreateAbsenceWSlow.ZfhhrGbbapiZgeeamsCreateabs();

response = client.ZfhhrGbbapiZgeeamsCreateabs(data);

It's still failing to connect to the SAP web service. The error I am receiving is "The HTTP request is unauthorized with client authentication scheme 'Negotiate'". I've also tried using

binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

which returned a similar error.

Does anybody have any further suggestions or ideas of where I am going wrong?


Now, this is all coming from my own experience so some of it may be wrong, but here's how I understand the process (I received no documentation and my company had no experience in calling SAP before I began doing it).

SAP WS calls are only supported by WCF BasicHttpBinding, and as far as I can tell, only using plain-text credentials. This means you will want to use IPSec or HTTPS if you need to make your communication private (outside intranet, or sensitive data within intranet). Our SAP server does not have HTTPS configured, but we use VPN with IPSec for external communication. Important to note is that, by default, SAP GUI also does not make communication private. In this situation, you are being no less secure by using the method detailed below than the business user down the hall who is looking up sensitive data in GUI 7.1. Here's how I connect to our SAP server internally:

        //Create binding
        //Note, this is not secure but it's not up to us to decide. This should only ever be run within
        //the VPN or Intranet where IPSec is active. If SAP is ever directly from outside the network,
        //credentials and messages will not be private.
        var binding = new BasicHttpBinding();
        binding.MaxReceivedMessageSize = int.MaxValue;
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
        binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;

        //Assign address
        var address = new EndpointAddress(Host);

        //Create service client
        var client = new SAP_RFC_READ_TABLE.RFC_READ_TABLEPortTypeClient(binding, address);

        //Assign credentials
        client.ClientCredentials.UserName.UserName = User;
        client.ClientCredentials.UserName.Password = Password;

As far as I have been able to determine, message-level security is not supported, and bindings other than basicHttpBinding (SOAP 1.1) are not supported.

As I said, this is all from experience and not from training, so if anybody can add something through comments, please do so.


I've faced the same problem and it seems I've found the sollution here: http://ddkonline.blogspot.com/2009/08/calling-sap-pi-web-service-using-wcf.html.

        CustomBinding binding = new CustomBinding();
        binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
        HttpsTransportBindingElement transport = new HttpsTransportBindingElement();
        transport.AuthenticationScheme = AuthenticationSchemes.Basic;
        //transport.ProxyAuthenticationScheme = AuthenticationSchemes.Basic;
        transport.Realm = "XISOAPApps";
        binding.Elements.Add(transport);
        var address = new EndpointAddress("https://foooo");
        ........ create client proxy class


        service.ClientCredentials.UserName.UserName = "<login>";
        service.ClientCredentials.UserName.Password = "<password>";

Unfortunatelly I'm not able to use WCF in my application, I have to stick with .NET 2.0 and WSE 3.0, and I wounder if anybody was able to find sollution to that?


After all this time, the client has finally obtained someone to deal with the issue from their SAP end of things. Turns out the WSDL files we were supplied were incorrect and the certification had been done wrong. I reran my code with the new WSDL files and it worked first time.


Does your certificate happen to be mapped to a valid user in your user store?

0

精彩评论

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

关注公众号