使用WCF适配器服务项目的SAP身份验证

我一直在试用BizTalk Adapter Pack,特别是SAP的东西。

我可以使用SAP绑定直接连接到SAP并从客户端应用程序(例如控制台,Windows,Web站点)运行RFC,完全没有问题。 我还使用编排,发送端口,接收端口等方式在BizTalk Server 2009中实现了所有这些功能。

但是,我想将SAP功能作为标准HTTP Web服务公开给内部用户,而不要求他们在PC上安装SAP绑定。

所以,我在Visual Studio中创建了一个“WCF Adapter Service”项目,然后按照向导。 然后,我为客户端创建了一个标准的Web应用程序,并使用“添加服务引用”添加了一个代理。 它一切正常,因为它找到了服务并添加了代理代码,但是当我尝试调用该服务时,出现错误SapErrorMessage =不完整的登录数据

我不知道该怎么做的是将SAP凭据从我的客户端Web应用程序传递到基本HTTP服务,然后再传递到SAP绑定。 如果我将SAP证书放入SAP连接字符串中,它一切正常,但这不是非常安全,我也想从客户端提供证书(即要求用户提供其SAP证书)。

在我看到的一些例子中,例如http://msdn.microsoft.com/en-us/library/dd788594(BTS.10).aspx,SAP凭证将通过HTTP标头传递。 不幸的是,我所看到的所有示例都展示了如何从SharePoint调用服务,其中有一个用于设置标题的对话窗口。 我没有使用SharePoint! 我已经尝试在我的客户端端点配置中添加“”部分,但这似乎不起作用。

那么,推荐将SAP凭证传递给通过“WCF适配器服务”向导创建的基本HTTP Web服务的推荐方式是什么?

有关信息,这是我的客户端Web应用程序中web.config的相关部分:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="RfcEndpoint" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
                <security mode="None">
                    <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
                    <message clientCredentialType="UserName" algorithmSuite="Default"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://xxxxxx/SAP_Service_1/Rfc.svc" binding="basicHttpBinding" bindingConfiguration="RfcEndpoint" contract="ServiceReference1.Rfc" name="RfcEndpoint">
            <headers>
                <SAP_Username>username</SAP_Username>
                <SAP_Password>password</SAP_Password>
            </headers>
        </endpoint>
    </client>
</system.serviceModel>

这是由WCF适配器服务项目向导生成的web.config:

<?xml version="1.0"?>
<configuration>
    <system.serviceModel>
        <services>
            <service behaviorConfiguration="customServiceBehavior" name="RfcClient">
                <endpoint address="" behaviorConfiguration="customEndpointBehavior" binding="basicHttpBinding" bindingConfiguration="RfcClientBindingConfig" name="RfcEndpoint" contract="Rfc"/>
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
            </service>
        </services>
        <behaviors>
            <endpointBehaviors>
                <behavior name="customEndpointBehavior">
                    <endpointBehavior usernameHttpHeader="SAP_Username" passwordHttpHeader="SAP_Password" adapterSecurityBridgeType="HTTPUsernamePassword"/>
                </behavior>
            </endpointBehaviors>
            <serviceBehaviors>
                <behavior name="customServiceBehavior">
                    <serviceMetadata httpsGetEnabled="true"/>
                    <serviceDebug includeExceptionDetailInFaults="true"/>
                    <serviceCredentials type="Microsoft.ServiceModel.Channels.AdapterServiceCredentials, Microsoft.ServiceModel.Channels, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                    <serviceAuthorization serviceAuthorizationManagerType="Microsoft.ServiceModel.Channels.AdapterServiceAuthorizationManager, Microsoft.ServiceModel.Channels, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
                        <authorizationPolicies>
                            <add policyType="Microsoft.ServiceModel.Channels.AdapterAuthorizationPolicy, Microsoft.ServiceModel.Channels, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
                        </authorizationPolicies>
                    </serviceAuthorization>
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <extensions>
            <behaviorExtensions>
                <add name="endpointBehavior" type="Microsoft.ServiceModel.Channels.AdapterEndpointBehavior, Microsoft.ServiceModel.Channels, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
            </behaviorExtensions>
        </extensions>
        <bindings>
            <basicHttpBinding>
                <binding name="RfcClientBindingConfig">
                    <security mode="None">
                        <transport clientCredentialType="None"/>
                        <message clientCredentialType="UserName"/>
                    </security>
                </binding>
            </basicHttpBinding>
            <sapBinding>
                <binding name="SAPBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" enableBizTalkCompatibilityMode="false" receiveIdocFormat="Typed" enableSafeTyping="false" generateFlatFileCompatibleIdocSchema="true" maxConnectionsPerSystem="50" enableConnectionPooling="true" idleConnectionTimeout="00:15:00" flatFileSegmentIndicator="SegmentDefinition" enablePerformanceCounters="false" autoConfirmSentIdocs="false" acceptCredentialsInUri="true" padReceivedIdocWithSpaces="false" sncLibrary="" sncPartnerName="" rfcAllowStartProgram="">
                    <dataTypesBehavior datsMinToDateTime="NULL" datsMaxToDateTime="NULL" invalidDatsToDateTime="ERROR" emptyDatsToDateTime="0001-01-01T00:00:00" emptyTimsToDateTime="0001-01-01T00:00:00" dateTimeMaxToDats="99991231" dateTimeMinToDats="00010101" timsMaxToDateTime="NULL" invalidTimsToDateTime="ERROR" dateTimeMaxToTims="235959" dateTimeMinToTims="000000" invalidNumcToInt="0" emptyNumcToInt="0" dateTimeNullToDats="SKIP" dateTimeNullToTims="SKIP"/>
                </binding>
            </sapBinding>
        </bindings>
        <client>
            <endpoint address="sap://CLIENT=300;LANG=EN;@a/XXXXXX/00?RfcSdkTrace=False&amp;AbapDebug=False" binding="sapBinding" bindingConfiguration="SAPBinding" contract="Rfc" name="SAPBinding_Rfc"/>
        </client>
    </system.serviceModel>
</configuration>

我对WCF有点新鲜,所以感谢所有帮助或指点!

谢谢

道格


终于有了工作!

首先,我需要将SAP用户名和密码添加为请求中的HTTP标头。 我试着首先编辑配置文件的简单解决方案,正如一些人所建议的:

<endpoint ....
  <headers>
    <HeaderName1>Header Value 1</HeaderName1>
    <HeaderName2>Header Value 2</HeaderName2>
  </headers>
</endpoint>

但是这不会添加HTTP标头,或者至少我无法使其工作。

我看了这里的优秀文章http://ericphan.info/blog/2010/6/3/adding-custom-http-header-to-all-wcf-requests.html,它解释了如何使用MessageInspector添加传出请求的HTTP标头。 它工作出色,但头文件在配置文件中定义。 我需要一种方法来设置代码中的标题。 也许会有一种适应这种代码的方式,但我并不聪明!

相反,我找到了其他一些例子,并将其解释为:

using (RfcClient client = new RfcClient("RfcEndpoint"))
{

    try
    {
        using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
        {

            HttpRequestMessageProperty httpRequestProperty;
            if (OperationContext.Current.OutgoingMessageProperties.ContainsKey(HttpRequestMessageProperty.Name))
            {
                httpRequestProperty = (HttpRequestMessageProperty)OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name];
            }
            else
            {
                httpRequestProperty = new HttpRequestMessageProperty();
            }
            httpRequestProperty.Headers.Add("SAP_Username", "dXNlcm5hbWU=");
            httpRequestProperty.Headers.Add("SAP_Password", "cGFzc3dvcmQ=");
            OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;

            ret = client.BAPI_SALESORDER_GETLIST(cust, null, null, null, po, null, salesOrg, transGroup, ref orders);

            GridView1.DataSource = orders;
            GridView1.DataBind();

        }

        client.Close();

        Label1.Text = DateTime.Now.ToString();

    }
    catch (CommunicationException ex)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(ex.Message);
        if (ex.InnerException != null) sb.Append("~" + ex.InnerException.Message);
        Label1.Text = sb.ToString();
        client.Abort();
    }
    catch (TimeoutException ex)
    {
        Label1.Text = ex.Message;
        client.Abort();
    }
    catch (Exception ex)
    {
        Label1.Text = ex.Message;
        client.Abort();
        throw;
    }

}

为了完整起见,这是服务的web.config文件:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
        <services>
            <service behaviorConfiguration="customServiceBehavior" name="RfcClient">
                <endpoint address="" behaviorConfiguration="customEndpointBehavior"
                    binding="basicHttpBinding" bindingConfiguration="RfcClientBindingConfig"
                    name="RfcEndpoint" contract="Rfc" />
                <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
            </service>
        </services>
        <behaviors>
            <endpointBehaviors>
                <behavior name="customEndpointBehavior">
                    <endpointBehavior usernameHttpHeader="SAP_Username" passwordHttpHeader="SAP_Password"
                        adapterSecurityBridgeType="HTTPUsernamePassword" />
                </behavior>
            </endpointBehaviors>
            <serviceBehaviors>
                <behavior name="customServiceBehavior">
                    <serviceMetadata httpsGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                    <serviceCredentials type="Microsoft.ServiceModel.Channels.AdapterServiceCredentials, Microsoft.ServiceModel.Channels, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
                        <serviceCertificate findValue="servername" storeLocation="LocalMachine"
                            storeName="My" x509FindType="FindBySubjectName" />
                    </serviceCredentials>
                    <serviceAuthorization serviceAuthorizationManagerType="Microsoft.ServiceModel.Channels.AdapterServiceAuthorizationManager, Microsoft.ServiceModel.Channels, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
                        <authorizationPolicies>
                            <add policyType="Microsoft.ServiceModel.Channels.AdapterAuthorizationPolicy, Microsoft.ServiceModel.Channels, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
                        </authorizationPolicies>
                    </serviceAuthorization>
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <extensions>
            <behaviorExtensions>
                <add name="endpointBehavior" type="Microsoft.ServiceModel.Channels.AdapterEndpointBehavior, Microsoft.ServiceModel.Channels, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            </behaviorExtensions>
        </extensions>
        <bindings>
            <basicHttpBinding>
                <binding name="RfcClientBindingConfig">
                    <security mode="Transport">
                        <transport clientCredentialType="None" />
                        <message clientCredentialType="UserName" />
                    </security>
                </binding>
            </basicHttpBinding>
            <sapBinding>
                <binding name="SAPBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
                    receiveTimeout="00:10:00" sendTimeout="00:01:00" enableBizTalkCompatibilityMode="false"
                    receiveIdocFormat="Typed" enableSafeTyping="false" generateFlatFileCompatibleIdocSchema="true"
                    maxConnectionsPerSystem="50" enableConnectionPooling="true"
                    idleConnectionTimeout="00:15:00" flatFileSegmentIndicator="SegmentDefinition"
                    enablePerformanceCounters="false" autoConfirmSentIdocs="false"
                    acceptCredentialsInUri="false" padReceivedIdocWithSpaces="false"
                    sncLibrary="" sncPartnerName="" rfcAllowStartProgram="">
                    <dataTypesBehavior datsMinToDateTime="NULL" datsMaxToDateTime="NULL"
                        invalidDatsToDateTime="ERROR" emptyDatsToDateTime="0001-01-01T00:00:00"
                        emptyTimsToDateTime="0001-01-01T00:00:00" dateTimeMaxToDats="99991231"
                        dateTimeMinToDats="00010101" timsMaxToDateTime="NULL" invalidTimsToDateTime="ERROR"
                        dateTimeMaxToTims="235959" dateTimeMinToTims="000000" invalidNumcToInt="0"
                        emptyNumcToInt="0" dateTimeNullToDats="SKIP" dateTimeNullToTims="SKIP" />
                </binding>
            </sapBinding>
        </bindings>
        <client>
            <endpoint address="sap://CLIENT=300;LANG=EN;@a/XXXXXX/00?RfcSdkTrace=False&amp;AbapDebug=False"
                binding="sapBinding" bindingConfiguration="SAPBinding" contract="Rfc"
                name="SAPBinding_Rfc" />
        </client>
    </system.serviceModel>
</configuration>

对于Web客户端应用程序:

<system.serviceModel>
    <behaviors />
    <extensions />
    <bindings>
            <basicHttpBinding>
                <binding name="RfcEndpoint" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
                    <security mode="Transport">
                        <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
                        <message clientCredentialType="UserName" algorithmSuite="Default"/>
                    </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
      <endpoint address="https://servername/SAP_Service_HTTP/Rfc.svc"
      binding="basicHttpBinding" bindingConfiguration="RfcEndpoint"
      contract="ServiceReference1.Rfc" name="RfcEndpoint" >
      </endpoint>>
    </client>
</system.serviceModel>

这使用传输安全性(SSL)来保护标题,但它没有工作。

注意练习的最后一步。 HTTP标头值需要Base64编码! 我不知道为什么,但它一定是SAP适配器期待他们。

道格


找到更简单的解决方案!

WCF很高兴在邮件正文中发送用户名/密码凭证,以提供受保护的邮件。 不知道为什么我以前没有想到它,但设置像这样的安全:

<security mode="TransportWithMessageCredential">

意味着Rohit的建议现在可行。

因此,服务web.config期望消息中的凭证并使用传输安全性:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
        <services>
            <service behaviorConfiguration="customServiceBehavior" name="RfcClient">
                <endpoint address="" behaviorConfiguration="customEndpointBehavior"
                    binding="basicHttpBinding" bindingConfiguration="RfcClientBindingConfig"
                    name="RfcEndpoint" contract="Rfc" />
                <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
            </service>
        </services>
        <behaviors>
            <endpointBehaviors>
                <behavior name="customEndpointBehavior">
                    <endpointBehavior adapterSecurityBridgeType="ClientCredentialUsernamePassword" />
                </behavior>
            </endpointBehaviors>
            <serviceBehaviors>
                <behavior name="customServiceBehavior">
                    <serviceMetadata httpsGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                    <serviceCredentials type="Microsoft.ServiceModel.Channels.AdapterServiceCredentials, Microsoft.ServiceModel.Channels, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
                        <serviceCertificate findValue="servername" storeLocation="LocalMachine"
                            storeName="My" x509FindType="FindBySubjectName" />
                    </serviceCredentials>
                    <serviceAuthorization serviceAuthorizationManagerType="Microsoft.ServiceModel.Channels.AdapterServiceAuthorizationManager, Microsoft.ServiceModel.Channels, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
                        <authorizationPolicies>
                            <add policyType="Microsoft.ServiceModel.Channels.AdapterAuthorizationPolicy, Microsoft.ServiceModel.Channels, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
                        </authorizationPolicies>
                    </serviceAuthorization>
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <extensions>
            <behaviorExtensions>
                <add name="endpointBehavior" type="Microsoft.ServiceModel.Channels.AdapterEndpointBehavior, Microsoft.ServiceModel.Channels, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            </behaviorExtensions>
        </extensions>
        <bindings>
            <basicHttpBinding>
                <binding name="RfcClientBindingConfig">
                    <security mode="TransportWithMessageCredential">
                        <transport clientCredentialType="None" />
                        <message clientCredentialType="UserName" />
                    </security>
                </binding>
            </basicHttpBinding>
            <sapBinding>
                <binding name="SAPBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
                    receiveTimeout="00:10:00" sendTimeout="00:01:00" enableBizTalkCompatibilityMode="false"
                    receiveIdocFormat="Typed" enableSafeTyping="false" generateFlatFileCompatibleIdocSchema="true"
                    maxConnectionsPerSystem="50" enableConnectionPooling="true"
                    idleConnectionTimeout="00:15:00" flatFileSegmentIndicator="SegmentDefinition"
                    enablePerformanceCounters="false" autoConfirmSentIdocs="false"
                    acceptCredentialsInUri="false" padReceivedIdocWithSpaces="false"
                    sncLibrary="" sncPartnerName="" rfcAllowStartProgram="">
                    <dataTypesBehavior datsMinToDateTime="NULL" datsMaxToDateTime="NULL"
                        invalidDatsToDateTime="ERROR" emptyDatsToDateTime="0001-01-01T00:00:00"
                        emptyTimsToDateTime="0001-01-01T00:00:00" dateTimeMaxToDats="99991231"
                        dateTimeMinToDats="00010101" timsMaxToDateTime="NULL" invalidTimsToDateTime="ERROR"
                        dateTimeMaxToTims="235959" dateTimeMinToTims="000000" invalidNumcToInt="0"
                        emptyNumcToInt="0" dateTimeNullToDats="SKIP" dateTimeNullToTims="SKIP" />
                </binding>
            </sapBinding>
        </bindings>
        <client>
            <endpoint address="sap://CLIENT=300;LANG=EN;@a/XXXXXX/00?RfcSdkTrace=False&amp;AbapDebug=False"
                binding="sapBinding" bindingConfiguration="SAPBinding" contract="Rfc"
                name="SAPBinding_Rfc" />
        </client>
    </system.serviceModel>
</configuration>

客户端web.config也进行了类似的配置:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="RfcEndpoint" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
                <security mode="TransportWithMessageCredential">
                    <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
                    <message clientCredentialType="UserName" algorithmSuite="Default"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="https://servername/SAP_Service_BASIC/Rfc.svc" binding="basicHttpBinding" bindingConfiguration="RfcEndpoint" contract="ServiceReference1.Rfc" name="RfcEndpoint"/>
    </client>
</system.serviceModel>

那么客户端代码就是:

string cust = "12345";
string po = "12345";
string salesOrg = "1234";
string transGroup = "0";

BAPIORDERS[] orders = new BAPIORDERS[0];
BAPIRETURN ret = new BAPIRETURN();

using (RfcClient client = new RfcClient("RfcEndpoint"))
{
    client.ClientCredentials.UserName.UserName = "username";
    client.ClientCredentials.UserName.Password = "password";

    try
    {
        ret = client.BAPI_SALESORDER_GETLIST(cust, null, null, null, po, null, salesOrg, transGroup, ref orders);

        GridView1.DataSource = orders;
        GridView1.DataBind();

        Label1.Text = DateTime.Now.ToString();

        client.Close();

    }
    catch (CommunicationException ex)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(ex.Message);
        if (ex.InnerException != null) sb.Append("~" + ex.InnerException.Message);
        Label1.Text = sb.ToString();
        client.Abort();
    }
    catch (TimeoutException ex)
    {
        Label1.Text = ex.Message;
        client.Abort();
    }
    catch (Exception ex)
    {
        Label1.Text = ex.Message;
        client.Abort();
        throw;
    }

}

完善!


不会将以下内容添加到客户端应用程序为您工作?

RfcClient client = new RfcClient();
client.ClientCredentials.UserName.UserName = "myusername";
client.ClientCredentials.UserName.Password = "mypassword";
链接地址: http://www.djcxy.com/p/17181.html

上一篇: SAP authentication with WCF Adapter Service project

下一篇: How do I force my .NET application to run as administrator?