8

の NT 資格情報を使用して RequestSecurityToken を積極的に発行するためのサンプル コードを誰か指摘できます Thread.CurrentPrincipal as ClaimsPrincipalか?

シナリオは、Windows 認証が有効になっている asp.net Web アプリです (したがって、認証済みの WindowsIdentity があります)。私の望みは、passiveRedirect を有効にするのではなく、STS をアクティブに呼び出し、.Net 4.5 ID ライブラリを使用してこれを行うことです。

Claims Helper for Windows PhoneUsing an Active STSなどのほとんどのコード サンプルでは、​​username/pwd 入力と UserNameWSTrustBinding を使用して資格情報を設定します。

channelFactory.CreateChannelWithActAsToken()解決策には、なりすましや、Windows ID から作成されたトークンを使用した呼び出しが含まれる可能性があると思いました。

-- 次の .Net4.5 コードは、/adfs/services/trust/13/windowsmixed エンドポイントにヒットしたときに GenericXmlSecurityToken を取得します。ただし、クレームはサイトが実行されているドメイン アカウントに対するものであり、認証されたユーザーのドメイン アカウントに対するものではありません。エンドポイントを /adfs/services/trust/13/kerberossmixed に切り替えると、いくつかの質問やフォーラムに記載されているように「交渉できません」というエラーが表示されますが、.Net 4.5 で提供されているソリューションを適用できません。Microsoft.IdentityModel から移植されていないクラスの 1 つは、KerberosWSTrustBinding です...

public static void CallSts()
{
    try
    {
        var wsMod = FederatedAuthentication.WSFederationAuthenticationModule;
        var appliesToEp = new EndpointReference(wsMod.Realm);
        var stsEp = new EndpointAddress(new Uri(wsMod.Issuer), EndpointIdentity.CreateSpnIdentity("stsSpn"));

        var msgBinding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential, false);
        msgBinding.Security.Message.EstablishSecurityContext = false;
        msgBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;

        using(var factory = new WSTrustChannelFactory(msgBinding, stsEp))
        {
            factory.Credentials.SupportInteractive = false;
            factory.TrustVersion = TrustVersion.WSTrust13;

            var myRst = new RequestSecurityToken
            {
                RequestType = RequestTypes.Issue,
                AppliesTo = appliesToEp,
                KeyType = KeyTypes.Bearer,
            };
                var channel = factory.CreateChannel();
                var stsToken = channel.Issue(myRst) as GenericXmlSecurityToken;

                if(stsToken != null)
                {
                    Log.DebugFormat("Reply Token is {0}", stsToken.GetType().Name);

                    var handlers = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlers;
                    var token = handlers.ReadToken(new XmlTextReader(new StringReader(stsToken.TokenXml.OuterXml)));
                    var identity = handlers.ValidateToken(token).First();
                    //TODO write to session
                }
                else
                {
                    Log.Debug("Reply Token is null.");
                }
        }
    }
    catch(Exception ex)
    {
        Log.Error("Rst.Call has failed", ex);
    }
}

@leastprivilege の提案として、次のコードを追加します。

    var user = Thread.CurrentPrincipal as ClaimsPrincipal;
var winId = user.Identity as WindowsIdentity;
if(winId != null)
{
    // shows my domain account after I was prompted for credentials;
    // my domain account does not exist on the client machine, so it is a true domain credential
    Log.DebugFormat("WindowsIdentity Name is {0}", winId.Name);
}
using(winId.Impersonate())
{
    // again, shows my domain account
    Log.DebugFormat("Impersonation Context {0}", WindowsIdentity.GetCurrent(true).Name);
    var channel = factory.CreateChannel();
    var stsToken = channel.Issue(myRst) as GenericXmlSecurityToken;
    // request is issued, but results in SecurityNegotiationException: The caller was not authenticated by the service.
}

「発信者はサービスによって認証されませんでした」で失敗します。同じ STS がパッシブ リダイレクト シナリオで私のドメイン アカウントを認証します。


アップデート:

この質問がかなりの数のビューを受け取ったという通知を受け取ったので、1 つの回避策として次のことを提案します: サーバーを委任用に構成しましたが (Dominick が以下で提案したように)、それでもダブルホップの問題を克服できませんでした。思い出すと、私たちは、ローカル IT 上の単純なネットワーク管理ポリシーから、どの企業も同様に直面する可能性のある障害にぶつかりました。そのため、Windows 認証を使用したサーバーに対してダブル ホップを介して偽装することは許可されていませんが、基本認証を使用してダブル ホップを介して資格情報を偽装することができます。これは、許容できる状況である場合とそうでない場合があります (この場合はイントラネット)。もしそうなら、あなたは追加するでしょう

msgBinding.Security.Message.NegotiateServiceCredential = true;

上記の ChannelBinding 構成に。

4

1 に答える 1

2

まあ-これは実際には些細なことではありません。そのためには、Kerberosの偽装と委任を行う必要があります。

まず第一に、なりすまし。Thread.CurrentPrincipalから取得したWindowsIdentityでImpersonate()を呼び出す必要があります。

WindowsIdentity.GetCurrentを呼び出すことで、偽装していることを確認できます。このIDは、(サーバーIDではなく)クライアントを指している必要があります。

次に、なりすまし中にWS-Trustリクエストを行う必要があります。これはおそらくデフォルトでは許可されていません。したがって、ネットワーク管理者は、STSへのサーバーIDの委任を構成する必要があります。

于 2013-01-10T07:09:09.567 に答える