Ron*_*rby 0 .net wcf web-services
我正在尝试使用新的WCF服务.该服务在分层安全性之前正在运行.现在我收到此错误:
An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail.
Server stack trace:
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception 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 MyProject.IntegrationSample.MyProjectService.IMyProjectService.GetData(Int32 value)
at MyProject.IntegrationSample.MyProjectService.MyProjectServiceClient.GetData(Int32 value) in C:\code\AdvancedFraudSolutions\MyProject4.0\MyProject.IntegrationSample\Service References\MyProjectService\Reference.cs:line 82
at MyProject.IntegrationSample.Program.Main(String[] args) in C:\code\AdvancedFraudSolutions\MyProject4.0\MyProject.IntegrationSample\Program.cs:line 22
At least one security token in the message could not be validated.
Run Code Online (Sandbox Code Playgroud)
这在跟踪日志中:
Message security verification failed.
Run Code Online (Sandbox Code Playgroud)
这是我的服务配置:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicBinding">
<security mode="TransportWithMessageCredential"/>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="MyProject.IntegrationServices.MyProjectService" behaviorConfiguration="basicServiceBehavior">
<endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding"
name="MyProjectServiceEndpoint" contract="MyProject.IntegrationServices.IMyProjectService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="basicServiceBehavior">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceAuthorization principalPermissionMode="UseAspNetRoles"
roleProviderName="AspNetSqlRoleProvider" />
<serviceCredentials>
<serviceCertificate findValue="MyServiceCert" x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider"
membershipProviderName="AspNetSqlMembershipProvider" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<diagnostics>
<messageLogging maxMessagesToLog="25000" logEntireMessage="true" logMessagesAtServiceLevel="false" logMalformedMessages="true"
logMessagesAtTransportLevel="true">
<filters>
<clear/>
</filters>
</messageLogging>
</diagnostics>
</system.serviceModel>
Run Code Online (Sandbox Code Playgroud)
这是我的测试客户端代码和配置:
static void Main(string[] args)
{
MyProjectServiceClient client = new MyProjectServiceClient();
client.ClientCredentials.UserName.UserName = "theuser";
client.ClientCredentials.UserName.Password = "thepass";
try
{
string result = client.GetData(100);
client.Close();
Console.WriteLine(result);
}
catch (Exception ex)
{
client.Abort();
PrintExceptionDetail(ex);
}
Console.ReadLine();
}
private static void PrintExceptionDetail(Exception ex)
{
StringBuilder detail = new StringBuilder();
while (ex != null)
{
detail.AppendLine(ex.Message);
detail.AppendLine(ex.StackTrace);
ex = ex.InnerException;
}
Console.WriteLine(detail);
Console.Write("Copy exception detail to clipboard? (y/n) ");
if (Console.ReadLine().ToLower() == "y")
{
Clipboard.SetText(detail.ToString());
}
}
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MyProjectServiceEndpoint" 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://localhost:44306/MyProjectService.svc" binding="basicHttpBinding" bindingConfiguration="MyProjectServiceEndpoint"
contract="MyProjectService.IMyProjectService" name="MyProjectServiceEndpoint"/>
</client>
</system.serviceModel>
Run Code Online (Sandbox Code Playgroud)
您可以看到我正在尝试使用basicHttpBinding,TransportWithMessageCredential安全性和成员资格/角色提供程序进行身份验证/授权.
这是使用IIS express开发的,将在IIS中托管.
错误的原因是什么?
我通过在服务主机web.config文件中添加计算机密钥来解决此问题.
服务跟踪日志没有帮助.它只给了我"消息安全验证失败".然后我启用了服务主机web.config文件的wcf服务事件日志,使用,
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="NewBehavior">
<serviceSecurityAudit auditLogLocation="Application" serviceAuthorizationAuditLevel="Failure" messageAuthenticationAuditLevel="Failure" suppressAuditFailure="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system>
</configuration>
Run Code Online (Sandbox Code Playgroud)
我在计算机应用程序事件日志中得到以下内容,
事件类型:错误事件源:ServiceModel审计4.0.0.0事件类别:MessageAuthentication事件ID:4日期:30/01/2013时间:3:18:27 PM用户:N/A计算机:CENTDAUD05109DL描述:消息身份验证失败.服务:: // mymachine:44304/UploadService.svc操作:http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT ClientIdentity:ActivityId:cf20ce8b-2e8c-45b5-9ab6-adc5051080f8 ProviderException:您必须指定非自动生成的计算机密钥才能以加密格式存储密码.指定不同的passwordFormat,或更改machineKey配置以使用非自动生成的解密密钥.
然后我将机器密钥添加到服务主机web.config并且它工作正常.下面是示例机器密钥.
<machineKey
validationKey=
"5AD524EF7BEB32A479F8095F8BF7653680066ADE66B5C78F80C3DC1F90
AA3D766F2B69304BFF88DEABEDE1E66D463C81FDEE0FC1A391AD90A6FD1294E7D243B1"
decryptionKey=
"0D7AE7BC7581976D76AC1D68C71BCBA978895CB792DC4F7B9F0D67774378A351"
validation="SHA1"
decryption="AES"/>
Run Code Online (Sandbox Code Playgroud)
参考文献,
http://intrepiddeveloper.wordpress.com/2008/08/07/security-event-logging-auditing/