首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WCF适配器服务项目SAP身份验证

WCF适配器服务项目SAP身份验证
EN

Stack Overflow用户
提问于 2010-12-06 16:11:52
回答 3查看 4.8K关注 0票数 0

我一直在试验BizTalk适配器包,特别是SAP的东西。

我能够连接到SAP并从客户端应用程序(例如控制台、Windows、网站)直接使用SAP绑定运行RFC,完全没有问题。我还让它在BizTalk Server 2009中使用编排、发送端口、接收端口等进行工作。

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

因此,我在Visual中创建了一个"WCF适配器服务“项目,并遵循了向导。然后,我为客户端创建了一个标准web应用程序,并使用“added”添加了一个代理。这一切都正常,因为它找到了服务并添加了代理代码,但是当我试图调用该服务时,我得到了错误的SapErrorMessage=Incomplete登录数据

我不知道如何将SAP凭据从我的客户端web应用程序传递到基本的HTTP服务,然后在SAP绑定上传递。如果我将SAP凭据放入SAP连接字符串中,则一切正常,但这并不十分安全,而且我还想提供来自客户端的凭据(即要求用户提供他们的SAP凭据)。

在我看到的一些示例中,例如http://msdn.microsoft.com/en-us/library/dd788594(BTS.10).aspx,SAP凭据是在headers中传递的。不幸的是,我看到的所有示例都将继续演示如何从SharePoint调用服务,其中有一个设置标头的对话框窗口。我不使用SharePoint!我尝试过在我的客户端点配置中添加一个"“部分,但这似乎行不通。

那么,向通过"WCF Adapter Service“向导创建的基本HTTP服务传递SAP凭据的推荐方法是什么?

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

代码语言:javascript
复制
<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>

这是由项目向导生成的web.config:

代码语言:javascript
复制
<?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有点陌生,所以任何帮助或指点都很感激!

谢谢

道格

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-12-09 15:50:39

找到了更简单的解决方案!

WCF很乐意在消息正文中发送用户名/密码凭据,前提是消息受到保护。不知道为什么我以前没有想过,但是像这样设置安全性:

代码语言:javascript
复制
<security mode="TransportWithMessageCredential">

意味着罗希特的建议现在起作用了。

因此,服务web.config需要消息中的凭据,并使用传输安全性:

代码语言:javascript
复制
<?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也被类似地配置:

代码语言:javascript
复制
<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>

然后,客户端代码就是:

代码语言:javascript
复制
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;
    }

}

太棒了!

票数 0
EN

Stack Overflow用户

发布于 2010-12-08 11:49:45

终于成功了!

首先,我需要将SAP用户名和密码作为HTTP头添加到请求中。我尝试了首先编辑配置文件的简单解决方案,就像一些人建议的那样:

代码语言:javascript
复制
<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将headers添加到传出请求中。它工作得很出色,但是头文件在配置文件中定义。我需要一种在代码中设置头的方法。也许会有一种方法来适应这段代码,但我没有那么聪明!

相反,我找到了一些其他的例子,并将其归结为:

代码语言:javascript
复制
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文件:

代码语言:javascript
复制
<?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>

对于网络客户端应用程序:

代码语言:javascript
复制
<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)来保护报头,但它不需要。

注意练习的最后转折。header值需要Base64编码!我不知道为什么,但肯定是SAP适配器期望他们这样做。

道格

票数 2
EN

Stack Overflow用户

发布于 2010-12-07 08:19:04

在客户端应用程序中添加以下内容不适合您吗?

代码语言:javascript
复制
RfcClient client = new RfcClient();
client.ClientCredentials.UserName.UserName = "myusername";
client.ClientCredentials.UserName.Password = "mypassword";
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4368426

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档