25

基本的な WCF UserName/Pwd セキュリティを破棄し、独自のカスタム クライアント資格情報を実装して、既定で提供される情報よりも多くの情報を保持する必要がありました。

私はこの MSDN の記事を読みましたが、機能しないため何かが欠けています。

まず、カスタム ClientCredentialsSecurityTokenManager を提供するいくつかのカスタム ClientCredentials があります。

public class CentralAuthCredentials : ClientCredentials
{
    public override System.IdentityModel.Selectors.SecurityTokenManager CreateSecurityTokenManager()
    {
        return new CentralAuthTokenManager(this);
    }
}

public class CentralAuthTokenManager : ClientCredentialsSecurityTokenManager
{
    private CentralAuthCredentials credentials;

    public CentralAuthTokenManager(CentralAuthCredentials creds) : base(creds)
    {
        this.credentials = creds;
    }

    public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
    {
        if (this.IsIssuedSecurityTokenRequirement(tokenRequirement) || tokenRequirement.TokenType == CentralAuthToken.TOKEN_TYPE)
            return new CentralAuthTokenProvider(credentials.UserId, credentials.UserPassword, credentials.ImpersonateId, credentials.LoginType);
        else
            return base.CreateSecurityTokenProvider(tokenRequirement);
    }

    public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver)
    {
        outOfBandTokenResolver = null;
        if (this.IsIssuedSecurityTokenRequirement(tokenRequirement) || tokenRequirement.TokenType == CentralAuthToken.TOKEN_TYPE)
            return new CentralAuthTokenAuthenticator();
        else
            return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver);
    }

    public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
    {
        return new CentralAuthTokenSerializer();
    }
}

アプリを実行すると、カスタム資格情報とトークン マネージャーが作成されます。ただし、メソッドでは:

CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
{
    ...
}

tokenRequirement.TokenType は、私のカスタム トークン以外のものとして認識されます。それは私の最初の質問をもたらします.WCFはトークンの要件が何であるかをどうやって知っているのですか?

また、方法:

public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
{
    return new CentralAuthTokenSerializer();
}

クライアントによって 1 回呼び出されますが、返されたトークン シリアライザーのメソッドが呼び出されることはありません。これは、カスタム トークンがネットワーク経由で送信されていないことを示しています。これは、カスタム トークンが必要であることを示す SecurityTokenRequirement が渡されないため、CreateSecurityTokenProvider() の呼び出しでカスタム トークン プロバイダーが返されなかったためだと思います。

クライアント側には、次のものがあります。

public class CentralAuthorizationManagerClient : ClientBase<ICentralAuthorizationManager>, ICentralAuthorizationManager, IDisposable
{
    public PFPrincipal GenerateToken()
    {
        if (!this.ChannelFactory.Endpoint.Behaviors.Contains(typeof(CentralAuthCredentials)))
            throw new ArgumentException("Must set CentralAuthCredentials before calling this method.");
        return base.Channel.GenerateToken();
    }

    public PFPrincipal GenerateToken(CentralAuthToken token)
    {
        this.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
        this.ChannelFactory.Endpoint.Behaviors.Add(new CentralAuthCredentials(token));
        return this.GenerateToken();
    }

これらのメソッドは基本的に、エンドポイントから既定の資格情報を削除し、カスタム CentralAuthCredentials の新しいインスタンスをアタッチすることになっています。(この削除/追加コンボは、どこかの MSDN 記事から入手しました)。

構成では:

    <behaviors>
        <endpointBehaviors>
            <behavior name="Server2ServerEndpointBehavior">
                <clientCredentials type="MyApp.Security.CentralAuthCredentials, MyApp">
                    <clientCertificate findValue="localhost" x509FindType="FindBySubjectName" storeLocation="CurrentUser" storeName="My" />
                    <serviceCertificate>
                        <authentication certificateValidationMode="None" revocationMode="NoCheck" />
                    </serviceCertificate>
                </clientCredentials>
            </behavior>
        </endpointBehaviors>
    </behaviors>

    <bindings>
        <wsHttpBinding>
            <binding name="wsHttpServer2Server">
                <security mode="Message">
                    <message clientCredentialType="UserName" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>

動作の clientCredentials タイプがカスタム クライアント資格情報に設定されていることに注意してください。ただし、現時点ではまだバインディングの clientCredentialType を「UserName」に設定しています。これは私の2 番目の質問をもたらします: 一体何 clientCredentialType="?" カスタム資格情報を使用している場合に設定されますか? MSDN によると、メッセージセキュリティで使用できる値は、 NoneWindowsUserNameCertificate、およびIssuedTokenです。

何か案は?うまくいけば、単純なものが欠けているだけですか?実装全体にはさらに 6 つのクラスがありますが、状況を理解するために必要なビットのみを含めようとしました...


更新#1:

私は一日中これに取り組んできましたが、いくつかの情報源のおかげで、欠けていたものの一部がこのページの最後のステップであることに気付きました。バインディングに TokenParameters を追加して、バインディングが何を認識できるようにするかです。トークンは次のようになります。それが私の元の最初の質問に対する答えです。「一体何がトークン要件を設定しているのですか?」答え: バインディングに割り当てられた TokenParameters です。

そこで、バインディングに TokenParameters を設定する次の拡張機能を追加しました。

public sealed class CentralAuthTokenBindingExtension : BindingElementExtensionElement
{
    public CentralAuthTokenBindingExtension()
        : base()
    {
    }

    public override Type BindingElementType
    {
        get { return typeof(SymmetricSecurityBindingElement); }
    }

    protected override System.ServiceModel.Channels.BindingElement CreateBindingElement()
    {
        X509SecurityTokenParameters protectionParams = new X509SecurityTokenParameters();
        protectionParams.InclusionMode = SecurityTokenInclusionMode.Never;

        SymmetricSecurityBindingElement innerBindingElement = new SymmetricSecurityBindingElement();
        innerBindingElement.EndpointSupportingTokenParameters.SignedEncrypted.Add(new CentralAuthTokenParameters());
        //innerBindingElement.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
        innerBindingElement.ProtectionTokenParameters = protectionParams;

        return innerBindingElement;
    }
}

    <extensions>
        <bindingElementExtensions>
            <add name="CentralAuthCreds" type="MyApp.Security.Configuration.CentralAuthTokenBindingExtension, MyApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
        </bindingElementExtensions>
    </extensions>

    <bindings>
        <customBinding>
            <binding name="wsHttpServer2Server">
                <CentralAuthCreds />
                <binaryMessageEncoding />
                <httpTransport />
            </binding>
        </customBinding>
    </bindings>

それは私をさらに一歩進めます。サーバーで新しい例外が発生しました。

"The security token manager cannot create a token authenticator for requirement ..."

WCF は、カスタム トークン ハンドラーではなく、既定のトークン マネージャーを使用してカスタム トークンを処理しようとしているようです (カスタム トークン ハンドラーのコンストラクターは呼び出されません)。clientの場合、次の構成があるため、これが発生していると思います。

<endpointBehaviors>
    <behavior name="Server2ServerEndpointBehavior">
        <clientCredentials type="MyApp.Security.CentralAuthCredentials, MyApp">

しかし、サーバーには、カスタム クライアントの資格情報を知らせるための同等のものはありません。それで、新しい質問: サーバーの構成のどこで、カスタム ClientCredentials が何であるかを伝えますか?


更新 #2:

さて、私はついにパズルをもう少し理解しました。クライアントが資格情報を送信すると考えて、ClientCredentials 実装のみを実装しました。クライアントはサービスを認証しないので、カスタム ServiceCredentials は必要ありません。まあ、私は間違っていました。指定された ServiceCredentials は ClientCredentials からのトークンを認証し、その逆も同様です。そのため、同じ TokenSerializer クラスと TokenAuthenticator クラスを渡すカスタム ServiceCredentials 実装を追加する必要がありました。

次の問題: WCF は、構成で指定された、UserName 認証で正常に機能していた x509 証明書を無視するようになりました。この質問に対して、まったく新しい質問を開きます。

4

1 に答える 1

1

作業中のアプリケーションで同様の問題に遭遇しましたが、残念ながら、カスタム資格情報を機能させることができなかったため、あきらめました。現在、ユーザー名/パスワード (クライアント資格情報) と証明書 (サービス資格情報) を使用しており、カスタムの暗号化された SOAP ヘッダーをサービス呼び出しに追加して、UserID などの追加情報を渡しています。

于 2009-02-19T09:59:33.710 に答える