我一直在试验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的相关部分:
<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:
<?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&AbapDebug=False" binding="sapBinding" bindingConfiguration="SAPBinding" contract="Rfc" name="SAPBinding_Rfc"/>
</client>
</system.serviceModel>
</configuration>我对WCF有点陌生,所以任何帮助或指点都很感激!
谢谢
道格
发布于 2010-12-09 15:50:39
找到了更简单的解决方案!
WCF很乐意在消息正文中发送用户名/密码凭据,前提是消息受到保护。不知道为什么我以前没有想过,但是像这样设置安全性:
<security mode="TransportWithMessageCredential">意味着罗希特的建议现在起作用了。
因此,服务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&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;
}
}太棒了!
发布于 2010-12-08 11:49:45
终于成功了!
首先,我需要将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将headers添加到传出请求中。它工作得很出色,但是头文件在配置文件中定义。我需要一种在代码中设置头的方法。也许会有一种方法来适应这段代码,但我没有那么聪明!
相反,我找到了一些其他的例子,并将其归结为:
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&AbapDebug=False"
binding="sapBinding" bindingConfiguration="SAPBinding" contract="Rfc"
name="SAPBinding_Rfc" />
</client>
</system.serviceModel>
</configuration>对于网络客户端应用程序:
<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适配器期望他们这样做。
道格
发布于 2010-12-07 08:19:04
在客户端应用程序中添加以下内容不适合您吗?
RfcClient client = new RfcClient();
client.ClientCredentials.UserName.UserName = "myusername";
client.ClientCredentials.UserName.Password = "mypassword";https://stackoverflow.com/questions/4368426
复制相似问题