[.NET Framework 3.5 セキュリティ/認証あれこれ] トランスポートレベルのカスタムな認証
環境:
Visual Studio 2008
こんにちは。
だいぶ間が空いてしまいましたが、今日は、WCF の認証について .NET Framework 3.5 で追加された仕組みを説明します。が、その前に、まず、既存の WCF (.NET Framework 3.0) がどうであったかという点をおさらいしておきましょう。(尚、ここでは、「認証」の切り口のみでおさらいしていますが、WCF のセキュリティ全般で言えば、暗号化や、特定のメソッドなどを特定のユーザだけに使わせるロール的な考え方など、Integrity, Confidentiality, Authorization といったさまざまな観点での考え方が含まれていて、必要におうじて利用することができるようになっています。)
WCF では、 以下の認証が可能となっていますが、それぞれに「トランスポートレベル」と、「メッセージレベル」という考え方があり、認証のタイプによっては、どちらか一方のみしか使えないようになっています。
ざっくりとした書き方ですが、トランスポートレベルとは、TCP や HTTP などのネットワークの層でおこなわれる認証で、メッセージレベルとは、その上位の層、例えば、SOAP のタグ付きメッセージのコンテンツそのもの、などにより認証の仕組みを実現しています。ですから、トランスポートレベルだと、既存の TCP や HTTP が持つセキュリティの機構をそのまま使うことになりますが、より根源的なレイヤで認証の仕組みが実現されていることになります。またその一方で、メッセージレベルでは、その上のメッセージの仕様如何でさまざまな方式やルールを定義できるため、より柔軟なセキュリティの仕組みを実装することができるようになっています。
1. None
クライアントは、Credential を必要としません
[config の構成例]
...
<security mode="None"/>
...
2. Basic (トランスポートレベルのみ)
クライアントは ID, パスワードを指定して接続する必要があります。(ユーザID, パスワードは、ダイアログボックスなどでユーザに入力を促すことになるでしょう。)
このID, パスワードは、既存の Basic 認証の仕組みを使用してクリアテキスト(ただし、通常はアルゴリズムによりエンコードされます)でヘッダーに設定されて渡されます。
[config の構成例]
...
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
...
3. Digest (トランスポートレベルのみ)
Basic と同様ですが、クリアテキストではなく、複合化が困難な一方向暗号化 (と書くと意味不明ですね。クライアントで暗号化されて、サーバに渡されます。サーバ側では複合化せず、同一性の照合のみをおこないます) が使用されます。
いわゆる Digest 認証と呼ばれる方式です。
[config の構成例]
...
<security mode="Transport">
<transport clientCredentialType="Digest" />
</security>
...
3. Windows (トランスポートレベル / メッセージレベル)
トランスポートレベルで指定すると、通常の Windows 認証のプロトコルのように、SSPI (Security Support Provider Interface) を使った Windows 認証をおこないます (その際、通常は、Kerberos が使用されます)。
また、メッセージレベルで指定すると、SOAP メッセージ交換の credential として、Windows の認証情報を使用します。
クライアント側では、認証情報は、クライアント側で使用されている Windows 認証の内容 (ドメインでのログインユーザの内容) が自動的に使用されることになります。(無論、クライアント側の .config に、Windows 認証を使うように指定をしておきましょう。)
[config の構成例]
...
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
...
または
...
<security mode="Message">
<transport clientCredentialType="Windows" />
</security>
...
4. Certificate (トランスポートレベル / メッセージレベル)
この指定も、トランスポートレベルとメッセージレベルで使用可能です。
トランスポートレベルで使用すると、SSL over HTTP, もしくは SSL over TCP によりトランスポートレベルでの機密性を確保できます。
メッセージレベルで使用すると、SOAP メッセージセキュリティに準じて、証明書によるSOAP メッセージの暗号化と署名がおこなわれます。メッセージレベルでは、SOAP の柔軟な規程により、トランスポートセキュリティ機構だけでは実現できない資格情報が提供可能です。
使用する証明書は、クライアント側の .config に記述します。(あるいは動的に指定したい場合は、コードで、クライアントクラスの ClientCredentials.ClientCertificate.SetCertificate メソッドを使います。)
[config の構成例]
...
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
...
または
...
<security mode="Message">
<transport clientCredentialType="Certificate" />
</security>
...
5.UserName (メッセージレベル)
上述の Basic や Digest のように、クライアントは明示的なユーザIDとパスワードの指定が必要です。ただし、Basic, Digest と違い、トランスポートレベルでなく、SOAP メッセージ交換の credential としてメッセージレベルで処理されます。
[config の構成例]
...
<security mode="Message">
<transport clientCredentialType="UserName" />
</security>
...
6. IssuedToken (メッセージレベル)
Windows CardSpace という .NET Framework 3.0 からの新しいアイデンティティフレームワークを使用して認証をおこないます。
Windows CardSpace を使ったデモや構成の記述については、
http://www.microsoft.com/japan/msdn/windows/windowsserver2008/tab/code/wcs.aspx
を参照してください。
.NET Framework 3.5 の新機能
上記の Basic, Digest, UserName ではユーザID とパスワードによる認証をおこなうと記載しましたが、どこの箱でユーザIDとパスワードを管理するのか疑問に思われるかもしれません。.config などで何の指定もしないと、通常は、(ドメインの) Windows 認証の情報が使用されます。ですので、クライアント側では、接続時にドメインユーザIDとパスワードを指定して接続することになります。
しかし、メッセージレベルの UserName では、さらに柔軟な構成が可能です。
UserName では、userNamePasswordValidationMode 属性というものを使用すると、例えば、MembershipProvider と指定すると ASP.NET のメンバーシップデータベースを使うことができたり、Custom を指定すると独自の認証処理をコードで記述 (アセンブリとしてコンパイル) して使用したり、といった、カスタムな認証を実現することが可能になっています。
と、だいぶ前置きが長くなりましたが(すみません、ほとんど前置きになりました)、Visual Studio 2008 からの .NET Framework 3.5 では、このカスタムの認証が、メッセージレベルだけでなく、トランスポートレベルでも使用できるようになっている、というのが今日の本旨です。.config やカスタムのユーザー名/パスワード検証コントロールの書き方は、概ね UserName のときと同様ですが、UserName ではなく、Basic を指定して使用することができるようになっているという点が異なります。
以下に、サンプルのソースコードが掲載されていますので是非ご参照ください。
http://msdn2.microsoft.com/ja-jp/library/aa702565.aspx