0

私はMSDNWCF-GettingStarted Tutorialを読みましたが、クライアントをドメイン内のあるマシンからドメイン内の別のマシンに移動しようとするまではうまくいきました。クライアントピースをネットワーク内の他のマシンに移動すると、SecurityNegotiationExceptionが発生しました。これが私がしたことです:

  1. サービス契約を定義しました(以下のコードブロック1を参照)。
  2. サービス契約を実装しました(以下のコードブロック2を参照)。
  3. サービスを実行するためのホストを作成しました(以下のコードブロック3を参照)。
  4. 実行svcutil.exeしてプロキシクラスと構成ファイルを生成しました(以下のコードブロック4を参照)。
  5. 4からの出力をクライアントプロジェクトにコピーしました。
  6. ホストに接続するクライアントを作成しました(以下のコードブロック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

(上記のコードブロックを使用して、スクロールして適切にフォーマットできるようにしました。引用符を使用しようとしましたが、読み取れませんでした。)

WCFのトレーニングを受けたユーザーにとって、このスタックトレースには明らかに明らかな問題がありますが、問題はわかりません。まず、この問題を解決してもらいたい。次に、優れたチュートリアルとトレーニング資料を知りたいです。 mark_sの回答にはいくつかのすばらしいリンクがあります。私はあなたのレビューのために 私のソースコードを圧縮しました。

ありがとう



コードブロック

コードブロック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:

C:\> svcutil.exe /language:vb /out:c:\generatedProxy.vb /config:c:\app.config http://scott:8000/ServiceModelSamples/service

コードブロック4からの出力:
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
4

2 に答える 2

3

「自己ホスト型サービス」(アプリケーションexeで実行されるサービス)は、IISまたはWebサービスでホストされるサービスと同じように世界中に公開できます。それはすべて、使用するバインディングによって異なります。例WSHttpBindingは、TCP/IPを使用するものを示しています。Windows上の通常のTCPベースのサーバー(IISを含む)と同様に、ファイアウォールなどがアクセスをブロックしない限り、これは世界中に公開されます。唯一の違いは、IISがデフォルトで行うように例が80ではなくポート8000​​にバインドすることです(例は、IISとの競合の可能性を回避するためにこれを行う可能性があります)。

を取得している理由を正確に追跡する必要がありますSecurityNegotiationException。デフォルトでは、セキュリティ機能はで有効になっていますがWSHttpBinding、これらはオフにすることができます。通常、クライアントとサーバーは同じドメイン上にある必要があります。そうでない場合は、認証を正常に行うために追加の作業を行う必要があります。

これはいくつかのヒットを取得します:https ://stackoverflow.com/search?q = SecurityNegotiationException

于 2009-11-25T00:17:45.540 に答える
2

そこにはたくさんの良いWCF資料があります-それはそれを見つけることの問題です:-)

次に、私がフォローしているブログがたくさんあります。もちろん、MSDNマガジンの「ServiceStation」列もあります(通常、より中級から上級のトピック)

于 2009-11-25T06:19:47.430 に答える