我已经通过了MSDN WCF - Getting Started Tutorial,直到我试图把客户从一台机器在我的域名转移到另一个在我的域名它去伟大。当我将客户peice移动到我的网络中的其他机器时,它给了我一个SecurityNegotiationException。这是我所做的:如何将MSDN“Self-Hosted”WCF示例从localhost移开?
- 我定义了一个服务合约(见下面的代码块1)。
- 我实施了服务合同(请参阅下面的代码块2)。
- 我创建了一个运行该服务的主机(请参阅下面的代码块3)。
- 冉
svcutil.exe
生成我的代理类和配置文件(请参见下面的代码块4)。 - 将输出从4复制到我的客户端项目中。
- 我创建了一个客户端连接到我的主机(请参见下面的代码块5)。
当我在自己的机器(SCOTT)上运行服务和客户端时,它工作正常。当我运行我的机器(SCOTT)上的服务和我的虚拟机上运行的客户端(SCOTT-VM)失败与以下堆栈跟踪:
Unhandled Exception: System.ServiceModel.Security.SecurityNegotiationException: SOAP security negotiation with 'http://scott:8000/ServiceModelSamples/Service/CalculatorService' for target 'http://scott:8000/ServiceModelSamples/Service/CalculatorService' failed. See inner exception for more details. ---> System.ComponentModel.Win32Exception: Security Support Provider Interface (SSPI) authentication failed. The server may not be running in an account with identity 'host/scott'. If the server is running in a service account (Network Service for example), specify the account's ServicePrincipalName as the identity in the EndpointAddress for the server. If the server is running in a user account, specify the account's UserPrincipalName as the identity in the EndpointAddress for the server.
at System.ServiceModel.Security.WindowsSspiNegotiation.GetOutgoingBlob(Byte[] incomingBlob)
at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState)
at System.ServiceModel.Security.IssuanceTokenProviderBase`1.GetNextOutgoingMessage(Message incomingMessage, T negotiationState)
at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout)
--- End of inner exception stack trace ---
Server stack trace:
at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout)
at System.ServiceModel.Security.SspiNegotiationTokenProvider.OnOpen(TimeSpan timeout)
at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Security.CommunicationObjectSecurityTokenProvider.Open(TimeSpan timeout)
at System.ServiceModel.Security.SecurityUtils.OpenTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout)
at System.ServiceModel.Security.SymmetricSecurityProtocol.OnOpen(TimeSpan timeout)
at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.ClientSecurityChannel`1.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(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)
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 System.ServiceModel.ICommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.ClientBase`1.System.ServiceModel.ICommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.ClientBase`1.Open()
at Client.Module1.Main() in C:\Projects\SKUNK\WCFServiceTutorial\Client\Module1.vb:line 11
(I使用的代码块的上方,使得它会滚动和格式很好,我试图用报价,它是不可读的。)
对于一个训练有素的WCF用户这个堆栈跟踪可能有明显的问题,但我看不出问题。首先,我想解决这个问题。其次,我想知道任何优秀的教程和培训材料。 mark_s有一些伟大的链接in his answer。我已经压缩了我的source code供您审查。
由于
代码块
码块1:
Imports System.ServiceModel
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples")> _
Public Interface ICalculator
<OperationContract()> _
Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double
<OperationContract()> _
Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double
<OperationContract()> _
Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double
<OperationContract()> _
Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double
<OperationContract()> _
Function Sin(ByVal n1 As Double) As Double
End Interface
码块2:
Public Class CalculatorService
Implements ICalculator
Public Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Add
Dim result As Double = n1 + n2
Console.WriteLine("Received Add({0}, {1})", n1, n2)
Console.WriteLine("Return: {0}", result)
Return result
End Function
Public Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Subtract
Dim result As Double = n1 - n2
Console.WriteLine("Received Subtract({0},{1})", n1, n2)
Console.WriteLine("Return: {0}", result)
Return result
End Function
Public Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Multiply
Dim result As Double = n1 * n2
Console.WriteLine("Received Multiply({0},{1})", n1, n2)
Console.WriteLine("Return: {0}", result)
Return result
End Function
Public Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Divide
Dim result As Double = n1/n2
Console.WriteLine("Received Divide({0},{1})", n1, n2)
Console.WriteLine("Return: {0}", result)
Return result
End Function
Public Function Sin(ByVal n1 As Double) As Double Implements ICalculator.Sin
Dim result As Double = Math.Sin(n1)
Console.WriteLine("Received Sin({0})", n1)
Console.WriteLine("Return: {0}", result)
Return result
End Function
End Class
代码块3:
Imports System.ServiceModel
Imports System.ServiceModel.Description
Module Module1
Sub Main()
Dim baseAddress As New Uri("http://scott:8000/ServiceModelSamples/Service")
Using selfHost As New ServiceHost(GetType(CalculatorService), baseAddress)
Try
' Add a service endpoint
selfHost.AddServiceEndpoint(GetType(ICalculator), New WSHttpBinding(), "CalculatorService")
' Enable metadata exchange
Dim smb As New ServiceMetadataBehavior()
smb.HttpGetEnabled = True
selfHost.Description.Behaviors.Add(smb)
selfHost.Open()
Console.WriteLine("The service is ready.")
Console.WriteLine("Press <ENTER> to terminate service.")
Console.WriteLine()
Console.ReadLine()
' Close the ServiceHostBase to shutdown the service.
selfHost.Close()
Catch ex As Exception
Console.WriteLine("An exception occurred: {0}", ex.Message)
selfHost.Abort()
End Try
End Using
End Sub
End Module
代码块4:从代码块4
C:\> svcutil.exe /language:vb /out:c:\generatedProxy.vb /config:c:\app.config http://scott:8000/ServiceModelSamples/service
输出:
的app.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ICalculator" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://scott:8000/ServiceModelSamples/Service/CalculatorService"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICalculator"
contract="ICalculator" name="WSHttpBinding_ICalculator">
<identity>
<userPrincipalName value="{MY_DOMAIN_NAME}" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
generatedProxy。VB:
'------------------------------------------------------------------------------
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:2.0.50727.4200
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict Off
Option Explicit On
<System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0"), _
System.ServiceModel.ServiceContractAttribute([Namespace]:="http://Microsoft.ServiceModel.Samples", ConfigurationName:="ICalculator")> _
Public Interface ICalculator
<System.ServiceModel.OperationContractAttribute(Action:="http://Microsoft.ServiceModel.Samples/ICalculator/Add", ReplyAction:="http://Microsoft.ServiceModel.Samples/ICalculator/AddResponse")> _
Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double
<System.ServiceModel.OperationContractAttribute(Action:="http://Microsoft.ServiceModel.Samples/ICalculator/Subtract", ReplyAction:="http://Microsoft.ServiceModel.Samples/ICalculator/SubtractResponse")> _
Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double
<System.ServiceModel.OperationContractAttribute(Action:="http://Microsoft.ServiceModel.Samples/ICalculator/Multiply", ReplyAction:="http://Microsoft.ServiceModel.Samples/ICalculator/MultiplyResponse")> _
Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double
<System.ServiceModel.OperationContractAttribute(Action:="http://Microsoft.ServiceModel.Samples/ICalculator/Divide", ReplyAction:="http://Microsoft.ServiceModel.Samples/ICalculator/DivideResponse")> _
Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double
<System.ServiceModel.OperationContractAttribute(Action:="http://Microsoft.ServiceModel.Samples/ICalculator/Sin", ReplyAction:="http://Microsoft.ServiceModel.Samples/ICalculator/SinResponse")> _
Function Sin(ByVal n1 As Double) As Double
End Interface
<System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")> _
Public Interface ICalculatorChannel
Inherits ICalculator, System.ServiceModel.IClientChannel
End Interface
<System.Diagnostics.DebuggerStepThroughAttribute(), _
System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")> _
Partial Public Class CalculatorClient
Inherits System.ServiceModel.ClientBase(Of ICalculator)
Implements ICalculator
Public Sub New()
MyBase.New
End Sub
Public Sub New(ByVal endpointConfigurationName As String)
MyBase.New(endpointConfigurationName)
End Sub
Public Sub New(ByVal endpointConfigurationName As String, ByVal remoteAddress As String)
MyBase.New(endpointConfigurationName, remoteAddress)
End Sub
Public Sub New(ByVal endpointConfigurationName As String, ByVal remoteAddress As System.ServiceModel.EndpointAddress)
MyBase.New(endpointConfigurationName, remoteAddress)
End Sub
Public Sub New(ByVal binding As System.ServiceModel.Channels.Binding, ByVal remoteAddress As System.ServiceModel.EndpointAddress)
MyBase.New(binding, remoteAddress)
End Sub
Public Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Add
Return MyBase.Channel.Add(n1, n2)
End Function
Public Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Subtract
Return MyBase.Channel.Subtract(n1, n2)
End Function
Public Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Multiply
Return MyBase.Channel.Multiply(n1, n2)
End Function
Public Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Divide
Return MyBase.Channel.Divide(n1, n2)
End Function
Public Function Sin(ByVal n1 As Double) As Double Implements ICalculator.Sin
Return MyBase.Channel.Sin(n1)
End Function
End Class
代码块5:
Imports System.ServiceModel
Module Module1
Sub Main()
'Dim client As MyCalcServiceRef.CalculatorClient = New MyCalcServiceRef.CalculatorClient()
'' Step 1: Create an endpoint address and an instance of the WCF Client.
Dim epAddress As New EndpointAddress("http://scott:8000/ServiceModelSamples/Service/CalculatorService")
Dim Client As New CalculatorClient(New WSHttpBinding(), epAddress)
Client.Open()
'Step 2: Call the service operations.
'Call the Add service operation.
Dim value1 As Double = 100D
Dim value2 As Double = 15.99D
Dim result As Double = client.Add(value1, value2)
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result)
'Call the Subtract service operation.
value1 = 145D
value2 = 76.54D
result = client.Subtract(value1, value2)
Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result)
'Call the Multiply service operation.
value1 = 9D
value2 = 81.25D
result = client.Multiply(value1, value2)
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result)
'Call the Divide service operation.
value1 = 22D
value2 = 7D
result = client.Divide(value1, value2)
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result)
'Call the Sin service operation.
value1 = 144D
result = client.sin(value1)
Console.WriteLine("Sin({0}) = {1}", value1, result)
' Step 3: Closing the client gracefully closes the connection and cleans up resources.
client.Close()
Console.WriteLine()
Console.WriteLine("Press <ENTER> to terminate client.")
Console.ReadLine()
End Sub
End Module
您是否在意为什么会遇到SecurityNegotiationException?或者你只是在寻找教程? – 2009-11-25 04:53:08
**当然**一个自托管的WCF服务可以向全世界开放!谁说不推荐自行托管?一些经验丰富的WCF大师实际上完全主张自我托管是现实生产系统唯一可行的选择...... – 2009-11-25 06:14:54
我写这个问题的时候已经很晚了,所以它不是很好。我在那里没有一个很棒的“问题”,只是我的一些随笔。我今天会重述一遍,看看自那之后是否有更多。我还会发布我的完整示例(包括源代码)和我的完整例外。感谢迄今为止所有的答案! – Scott 2009-11-25 14:42:08