2010-09-08 56 views
7

He escrito una aplicación de Windows para probar una conexión a los servicios web SAP de un cliente. La llamada al servicio web requiere seguridad del certificado X509.Conexión al servicio web de SAP desde la aplicación C# .NET

Después de leer varios artículos en Internet, he encontrado tres formas de adjuntar el certificado X509 a la llamada del servicio web. Lamentablemente, todos estos intentos devuelven un '401 acceso no autorizado'. Sin embargo, puedo conectarme al servicio web a través de la URL en IE.

¿Alguien tiene alguna pregunta sobre lo que puedo estar haciendo mal? Estoy usando WSE 3.0 y los tres métodos que estoy usando para fijar el certificado son los siguientes: -

Certificado

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

simbólico Política

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

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

GetSecurityToken() y GetSecuirtyCertificate buscan en el almacén de certificados. El SAPX509Assertion hace esto: -

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

actualización bien, tengo una llamada de WCF ahora en su lugar. No pude usar el método BasicHttpBinding mostrado por Eugarps ya que se quejaba de que me estaba conectando a una dirección https y esperaba http ... lo cual tenía sentido. El código que ahora tengo es: -

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 
var 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); 

Todavía no se puede conectar al servicio web de SAP. El error que recibo es "La solicitud HTTP no está autorizada con el esquema de autenticación del cliente 'Negociar'". También probé usando

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

que arrojó un error similar.

¿Alguien tiene alguna otra sugerencia o idea de dónde me estoy equivocando?

+0

'ZfhhrGbbapiZgeeamsCreateabsResponse' ... Mis ojos ... –

+0

Lo sé! No es el más fácil de usar de las convenciones de nombres. – grimorde

Respuesta

-1

Después de todo este tiempo, el cliente finalmente ha obtenido a alguien para tratar el problema desde el final de SAP. Resulta que los archivos WSDL que se nos proporcionaron eran incorrectos y que la certificación se había hecho mal. Volví a cambiar mi código con los nuevos archivos WSDL y funcionó por primera vez.

+0

Esto no es una respuesta. Debe eliminar su pregunta, ya que no ayuda a nadie. – ataravati

-2

¿Su certificado ha sido mapeado a un usuario válido en su tienda de usuario?

+0

El certificado ha sido generado por los chicos al final de SAP, pero debo suponer que la respuesta es afirmativa si IE recupera el certificado y lo utiliza con éxito. – grimorde

+0

Pregunte en los comentarios a la pregunta, no publique preguntas en respuesta. – Restuta

4

Ahora, todo esto proviene de mi propia experiencia, por lo que parte puede ser incorrecto, pero así es como entiendo el proceso (no recibí documentación y mi empresa no tenía experiencia en llamar a SAP antes de comenzar a hacerlo).

Las llamadas a SAP WS solo son compatibles con WCF BasicHttpBinding, y hasta donde puedo decir, solo usa credenciales de texto sin formato. Esto significa que querrá usar IPSec o HTTPS si necesita hacer que su comunicación sea privada (fuera de la intranet, o datos confidenciales dentro de la intranet). Nuestro servidor SAP no tiene configurado HTTPS, pero usamos VPN con IPSec para la comunicación externa. Es importante tener en cuenta que, de forma predeterminada, SAP GUI tampoco hace que la comunicación sea privada. En esta situación, no está menos seguro utilizando el método que se detalla a continuación que el usuario comercial que busca datos confidenciales en GUI 7.1. He aquí cómo me conecto a nuestro servidor SAP internamente:

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

Por lo que yo he podido determinar, no es compatible con la seguridad a nivel de mensajes, y los enlaces que no sea basicHttpBinding (SOAP 1.1) no son compatibles.

Como dije, esto es todo por experiencia y no por capacitación, así que si alguien puede agregar algo a través de comentarios, hágalo.

+0

Además, el ejemplo que publiqué usa enlaces creados dinámicamente que deshabilitarán el almacenamiento en caché de ChannelFactory. Si alguien usa este ejemplo en producción, téngalo en cuenta. – Sprague

+0

Estaba usando el proceso WSE3.0, pero veré la reescritura usando WCF y su ejemplo anterior. – grimorde

2

He enfrentado el mismo problema y parece que he encontrado la solución aquí: 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>"; 

Desafortunadamente no soy capaz de usar WCF en mi solicitud, tengo que seguir con .NET 2.0 y 3.0 WSE, y yo wounder si alguien era capaz de encontrar sollution a eso?

Cuestiones relacionadas