[英]WCF Client Using Certificate and Username/Password credentials?
我正在从ASP.NET使用公司内部的Web服务。 我已经使用svcutil.exe连接到服务并从wsdl生成绑定和类。 我能够连接到不需要身份验证的开发版本。 现在我们增加了安全性。 我的新URI使用https,但也需要用户凭据。
我是WCF的新手,正在尝试确定配置此方法的方法。 从我在MSDN上的阅读来看,似乎正在使用该方法。
更新:这是我一直在尝试的最新代码。 这包含了来自答案的反馈:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="svcBehavior">
<serviceCredentials>
<serviceCertificate storeLocation="CurrentUser"
storeName="My"
x509FindType="FindByThumbprint"
findValue="xx xx xx etc"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="CustomerPaymentProgramSOAPBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://***URL***"
binding="wsHttpBinding" bindingConfiguration="CustomerPaymentProgramSOAPBinding"
contract="CppService.CustomerPaymentProgramService" name="CustomerPaymentProgramService">
</endpoint>
</client>
</system.serviceModel>
这是调用代码:
using (var svc = new CustomerPaymentProgramServiceClient())
{
svc.ClientCredentials.UserName.UserName = "*******";
svc.ClientCredentials.UserName.Password = "*******";
var request = new GetServiceDataProgramRequest()
{
CustomerAccountId = Convert.ToInt64(customerAccountId)
};
svc.Open();
var response = new GetServiceDataProgramResponse();
var metaData = new RequestMetadata()
{
ClientIPAddress = "xx.xx.xx.xx",
TrackingNumber = "1",
UserID = "1"
};
svc.GetAccountData(metaData, request, out response);
}
我收到一条错误消息,指出我正在通过请求传递匿名证书。 使用更新的代码,现在我收到另一个异常:
更新:
使建议的修改以及删除从使用块的服务呼叫(每经过此文章),我现在得到一个MessageSecurityException:
Error message:
-$exception {"The HTTP request is unauthorized with client authentication scheme 'Anonymous'.
The authentication header received from the server was 'Basic realm=\"Spring Security Application\"'."}
System.Exception {System.ServiceModel.Security.MessageSecurityException}
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest request, HttpWebResponse response, WebException responseException, HttpChannelFactory factory)
at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory factory, WebException responseException)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.DoOperation(SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.GetTokenCore(TimeSpan timeout)
at System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionClientSettings`1.ClientSecuritySessionChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)
at System.ServiceModel.Channels.ServiceChannel.EnsureOpened(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)\r\n\r\nException rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at [ServiceName].GetAccountData(svcRequest request)
at [ServiceName].GetAccountData(GetAccountDataRequest request)
in c:\\[Project]\\service references\\[ServiceName]\\reference.cs:line 3480
at c:\\[Project]\\service references\\[ServiceName](RequestMetadata RequestMetadata, ServiceRequest, ServiceResponse& ServiceResponse)
in c:\\[Project]\\service references\\[ServiceName]\\reference.cs:line 3487
at c:\\[Project]\\service references\\[ServiceName].CheckAccountForPaymentPlan(String customerAccountId)
in c:\\[Project]\\service references\\[ServiceName]\\\\PlanCheckService.cs:line 32
使用TransportWithMessageCredential
,您可以指定将使用消息安全性来保护单个消息,这需要客户端凭据(用户名和密码)。 您需要类似于msdn链接中的配置的内容,如下所示:
<wsHttpBinding>
<binding name="WsHttpBinding_ICalculator">
<security mode="TransportWithMessageCredential" >
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
这不需要为客户端凭据指定证书。 传输安全性(使用https和有效的ssl证书)的工作方式与网站的工作方式相同,不需要用户提供其他凭据/证书。 来自受信任证书颁发机构的有效证书已安装在服务器上(客户端计算机能够验证它们),并且握手过程可保护通道。 这不需要您在配置中设置clientCrdentials
。 您只需要安装一个有效的证书(或dev的测试证书)并配置服务器配置,使其指向类似于以下内容的服务器:
<behaviors>
<serviceBehaviors>
<behavior name="mySvcBehavior">
<serviceCredentials>
<serviceCertificate findValue="contoso.com"
x509FindType="FindByIssuerName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
尝试从服务器配置中删除< transport clientCredentialType="Certificate" />
作为启动器,更新服务引用,并确保您的证书正常工作和配置。 如果仍然有问题,请发布实际的例外情况和更多配置。
要获得良好的WCF来源,请尝试: CodePlex ,当我开始使用WCF时,它可以无休止地帮助我。 不同的应用程序场景提供有用的清单,以帮助确保您不会错过配置中的任何步骤。
祝好运
更新:
一旦通道出现故障,就需要重新创建它,因为在重置之前您将无法与该服务进行通信。 因此,添加检查以重新创建它:
If svc.State = CommunicationState.Faulted Then....
尝试删除svc.Open()
行,因为我从未真正使用过它。 我检查了msdn的用法详细信息,但得到了大约2行无用的信息。 设置服务后,您应该能够与之通信,而不必专门打开它。 不知道这是否会有所作为?!
其他要检查的内容:-您可以右键单击该服务并在浏览器中查看而不会出现问题吗? -在IIS
中,您可以查看目录安全性中的证书而没有任何问题吗? -在进行服务调用之前进行调试,并检查凭据是否已正确分配。 -检查服务器事件查看器是否包含与请求一起记录的任何信息(如果到达该距离)。
另外,这是我使用ex.GetBaseException.GetType
来确定问题的一些异常:
ServiceModel.EndpointNotFoundException
ServiceModel.Security.MessageSecurityException
基本异常ServiceModel.FaultException
“ FailedAuthentication
”-用户输入的错误凭证
“ InvalidSecurity
”-数据库错误-任一帐户无权访问数据库,Web配置中的数据库名称不正确,数据库中的用户密码已过期
“ InvalidRequest
”-证书可访问性问题-检查服务帐户是否有权访问证书
基本异常Net.WebException
基本异常IdentityModel.Tokens.SecurityTokenValidationException
基本异常System.ServiceModel.CommunicationException
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.