使用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&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&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&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?