29

私はクライアント/サーバー アプリケーションで作業しており、クライアントがユーザーのログオン資格情報を使用してサーバーに対して自身を認証するようにしたいのですが、ユーザーがユーザー名とパスワードを入力する必要はありません。パスワードを安全に処理する責任を負いたくないのは確かです。ユーザーが自分が誰であるかを証明するだけで、サーバーは先に進み、コマンドを許可/拒否できます。

ユーザーはドメインの一部であるため、ログイン時に作成したログオン資格情報を使用できるようにしたいと考えています。

私はどのような種類の Web サービスも使用していませんし、使用したくもありません。私はクライアント ソフトウェアとサーバー ソフトウェアの両方を管理しており、どちらも純粋な C# で記述されており、作業を完了するために古き良きソケットを使用しています。

私は純粋な C#/.Net でこれを行うことを好みますが、安全でない C# を使用して、win32 API に pinvokes することにオープンです。

Windows での SSPI について少し読んだことがありますが、この種のアプリケーション開発は私にとって初めてのことなので、暗闇の中で感じています。

誰もこれを行う方法を知っていますか? SSPIは道ですか?C# 内から SSPI を使用するにはどうすればよいですか? コードの移植性を維持できる .Net ネイティブの方法はありますか?

4

5 に答える 5

1

「サーバーはどのようにしてクライアントが本人であることを確認するのですか?」

回答:ハンドシェイクのすべてのラウンドトリップが正常に終了した場合、つまり両方

  • InitializeSecurityContext「OK」を返します
  • AcceptSecurityContext「OK」を返します

これは、クライアントの Windows ログイン資格情報が本物であることが確認されたことを意味します。

AcceptSecurityContextは、(6番目のパラメーターCtxtHandleを介して) セキュリティ コンテキストを出力します。

このコンテキスト ハンドルには、クライアントの Windows ログイン ユーザー名が含まれます。サーバーはQueryContextAttributesExを呼び出すことで、クライアントの Windows ユーザー名を取得できます。

SecPkgContext_NativeNames pinfo;
QueryContextAttributesEx(&m_securitycontext, SECPKG_ATTR_NATIVE_NAMES, &pinfo);

これにより、Native Names構造が設定されます。

SecPkgContext_NativeNames 
{
   SEC_CHAR *sClientName;
   SEC_CHAR *sServerName;
}

pinfo.sClientNameは、クライアントの実際のログイン ユーザー名です。

: 以前のハンドシェイクでは、セキュリティ コンテキストの真実性が既に保証されているため、サーバーはpinfo.sClientNameクライアントの実際の Windows ユーザー名にすぎないと認識します。

于 2019-02-28T02:05:07.593 に答える
0

WCF が構成ファイル、エンドポイント セキュリティ、およびメッセージ/トランスポート セキュリティで多くのことを処理することを忘れていたため 、WindowsIdentity (認証に適しています) で完全に失敗しました。

NegotiateStreamを試しましたか? 与えられた例は、ニーズにより適しているようです。読み取り/書き込みを許可する前に、認証にKerberosを使用します。を使用するCredentialCache.DefaultNetworkCredentialsと、パスワードを照会する必要がなくなります。

于 2014-06-25T21:57:39.577 に答える
0

ニコラは正しいです。あなたがしていることを達成するための .NET ネイティブの方法はありません (少なくとも、低レベルの .NET Sockets サポートを使用しないでください)。相互運用のブラック マジックを実行するために内部に潜入することは確かにできますが、クライアントとサーバーの両方が制御下にある場合は、スタックを少し上に移動し、WCF などの高レベルの API を使用することを検討することをお勧めします。 Windows 統合認証の .NET ネイティブ サポートがあります。

あなたの質問とあなたが説明した環境に基づいて、NetTcpBinding を使用することができます。これは、探している認証/アイデンティティ フローの配管だけでなく、高いパフォーマンスも提供します (承認を処理するためのかなりクリーンな方法も提供します)。 ServiceAuthorizationManager クラスを使用します)。あなたのアプリ/サービスの詳細を知らなければ、あなたがやろうとしていることを実装するための「ハウツー」を提供することはできませんが、合理的に単純な例を含むドキュメントを紹介することはできます.

于 2014-06-19T12:24:07.873 に答える
-1

WindowsIdentity を操作しようとしたことがありますか?
Pure C#/.Net、シリアライズ可能、および GetCurrent() は実行アカウントを返します。


セキュリティトークン
ユーザーは、リクエストに便乗して一連のクレームをアプリケーションに配信します。Web サービスでは、これらのクレームは SOAP エンベロープのセキュリティ ヘッダーで伝達されます。ブラウザー ベースの Web アプリケーションでは、クレームはユーザーのブラウザーから HTTP POST 経由で到着し、セッションが必要な場合は後で Cookie にキャッシュされる場合があります。セキュリティ トークンは、発行機関によってデジタル署名されたシリアル化されたクレームのセットです。署名は重要です。これにより、ユーザーが大量のクレームを作成して送信しただけではないことを保証できます。暗号化が必要ない、または望ましくないセキュリティの低い状況では、署名されていないトークンを使用できますが、それはこのホワイト ペーパーで取り上げるシナリオではありません。WIF のコア機能の 1 つは、セキュリティ トークンを作成して読み取る機能です。WIF と .NET Framework の基盤となる配管は、すべての暗号化の面倒な作業を処理し、読み取り可能な一連のクレームをアプリケーションに提示します。

Windows Identity Foundation のホワイトペーパーから引用

あなたの主な質問は:

「ログオン資格情報を使用してユーザーを認証する純粋な C#/.NET の方法はありますか?」

WindowsIdentity は、ドメイン コントローラーによって発行された認証トークンであり、現時点では最良のアプローチのように思えます。


最初に投稿したとき、私は WindowsIdentity についてほとんど知りませんでしたが、問題や制約に役立つと感じました。いろいろ読んで、やっとこのページにたどり着きました。
WIF の導入は一目瞭然です。WindowsIdentity は、Windows ベース/ロール ベースのセキュリティ問題のために設計された .NET フレームワークの新しいセットです。
SSPI、Kerberos は Windows 認証プロセス全体の一部であり、ユーザー/マシン/プロセスによって取得されたログオン トークンはドメイン コントローラーによって付与され、新しい WindowsIdentity オブジェクトを「単純に」インスタンス化するだけでは取得できません。この種の違法なインスタンス化が存在すると、Windows セキュリティ モデル全体 (ドメイン、UAC など) が機能しなくなります。

これは、「BUILTIN\Administrateurs」の一部でない場合に例外をスローする (非常に!) 小さなコンソール プログラムです (必要に応じてグループ名を変更してください)。「管理者として実行」するたびに、プログラムはエラーなしで終了します。
アクセス許可の非常に大きなセットがあり、すべての要求は要求ベースです (ID は xxx のメンバーですか?)

using System;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;

namespace WindowsIdentityTest
{
    class Program
    {
        [PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
        static string SomeServerAction()
        { return "Authenticated users can access"; }

        [PrincipalPermission(SecurityAction.Demand, Role = "BUILTIN\\Administrateurs")]
        static string SomeCriticalServerAction()
        { return "Only Admins can access"; }

        static void Main(string[] args)
        {
            //This allows to perform security checks against the current Identity.   
            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);

            try
            {
                Console.WriteLine(SomeServerAction());
                Console.WriteLine(SomeCriticalServerAction());

            }
            catch (SecurityException sec)
            {
                Console.WriteLine(string.Format("{0} : {1}\n------------\n{2}"
                    , sec.GetType()
                    , sec.Message
                    , sec.StackTrace));
            }
            catch (Exception ex)
            {
                Console.WriteLine("This shall not appen.");
            }
            Console.WriteLine("Press enter to quit.");
            Console.ReadLine();
        }
    }
}

これが役立つことを願っています。

于 2014-06-19T21:20:25.087 に答える