- - PR -
WCFの認証にについての質問です
1
投稿者 | 投稿内容 |
---|---|
|
投稿日時: 2008-02-07 00:14
《開発環境》
Windows VISTA Ultima + VS2008 + IIS + WCF WCFを利用して、ユーザ認証をプログラムしているのですが、 認証の際の必須条件なのか、設定がおかしいいのかわからないので、 質問させていただきます。 やりたいことは、 WCFを利用して、「カスタム ユーザー名およびパスワード検証」です。 http://msdn2.microsoft.com/ja-jp/library/aa702565(vs.80).aspx サンプル通りに作成して実行すると、 「サービス証明書が指定されていません。ServiceCredentials で サービス証明書を指定してください。」 のエラーが発生します。 そこで、証明書が必要らしいことから、 こちらのサンプルをみながら、 http://msdn2.microsoft.com/ja-jp/library/aa354513(VS.85).aspx 証明書の設定を行いました。 動作するのは確認できたのですが、正常に動作するのは、ASP.NET開発サーバーのみ で、IISに移行したら、 「System.Security.Cryptography.CryptographicException: キー セットが ありません。」 というエラーが発生します。 実際わからないところが、 WCFのユーザ認証を行う際には、必ずX.509 証明書が必要ということなのでしょうか? また、ユーザ認証を、ASP.NETのメンバシップを利用する場合にも証明書が必要という ことなのでしょうか? 以上、わかる方がいらっしゃいましたら、ご教授をお願いいたします。 |
|
投稿日時: 2008-02-07 08:38
とりあえず自己解決しました。
やりたかったのは、WCFを使って、カスタムなユーザIDとパスワードを、 サーバー側で独自に判断し、認証されなかった場合は、OperationContract を実行させないというのをしたかったのです。 実際の配置環境は、インターネット上にサーバを立てて、IISでWCFをホスト させます。誰でもサービスを呼び出せないように認証を行い、さらに データは、wsHttpBindingで暗号化させて、クライアントとの通信を行います。 以下の方法で、ローカルでは実現できました。実際の環境では、どうなのか まだ不明な点もあります。ここはおかしいという点がありましたら、ご指摘を お願いいたします。 ------------------------------------------------------------------------- 1.WCFプロジェクトの作成 ------------------------------------------------------------------------- [ファイル]→[新規作成]→[プロジェクト]→[WEB]→[WCFサービスアプリケーション]で作成。 ------------------------------------------------------------------------- 2.Service1.svc.cs のコードに、「CustomUserNameValidator」を追加。 また、参照の追加で、「System.IdentityModel」を追加 ------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using System.IdentityModel.Selectors; using System.IdentityModel.Tokens; using System.Security.Principal; using System.ServiceModel; namespace WcfService1 { public class Service1 : IService1 { public string GetData(int value) { return string.Format("You entered: {0}", value); } public CompositeType GetDataUsingDataContract(CompositeType composite) { if (composite.BoolValue) { composite.StringValue += "Suffix"; } return composite; } } public class CustomUserNameValidator : UserNamePasswordValidator { public override void Validate(string userName, string password) { if (null == userName || null == password) { throw new ArgumentNullException(); } // ここで、DBなどからの情報を元に、任意に認証が可能 if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset")) { throw new SecurityTokenException("Unknown Username or Incorrect Password"); } } } } ------------------------------------------------------------------------- 3.Web.configの変更 ------------------------------------------------------------------------- <system.serviceModel> <services> <service name="WcfService1.Service1" behaviorConfiguration="WcfService1.Service1Behavior"> <!-- Service Endpoints --> <endpoint address="" binding="wsHttpBinding" contract="WcfService1.IService1" bindingConfiguration="Binding1"> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <bindings> <wsHttpBinding> <!-- メッセージ セキュリティを指定し、資格情報の種類を UserName に指定するバインディングを構成 --> <binding name="Binding1"> <security mode="Message"> <message clientCredentialType="UserName" /> </security> </binding> </wsHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="WcfService1.Service1Behavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="false"/> <!-- ここでカスタム認証、証明書を指定 --> <serviceCredentials> <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WcfService1.CustomUserNameValidator, WcfService1"/> <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" /> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> ------------------------------------------------------------------------- 3.証明書を作成するためのバッチファイルを作成 以下の makecert.exe や、certmgr.exeなどは、パスを通してください。 また、FindPrivateKey.exe は http://www.microsoft.com/downloads/details.aspx?FamilyId=2611A6FF-FD2D-4F5B-A672-C002F1C09CCD&displaylang=en のサンプルをダウンロードして、展開すると WCF_WF_CardSpace_Samples\WCF\Tools\FindPrivateKey にプロジェクトが あるので、これをビルドして利用します。 ------------------------------------------------------------------------- set SERVER_NAME=localhost set COMPUTERNAME=ここにコンピュータ名 makecert.exe -sr LocalMachine -ss My -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe echo ************ echo 証明書の秘密キーに関する権限の付与 echo ************ certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -s TrustedPeople echo ************ echo 証明書の秘密キーに関する権限の付与 echo ************ for /F "delims=" %%i in ('"FindPrivateKey.exe" My LocalMachine -n CN^=%SERVER_NAME% -a') do set PRIVATE_KEY_FILE=%%i set WP_ACCOUNT=NT AUTHORITY\NETWORK SERVICE (ver | findstr /C:"5.1") && set WP_ACCOUNT=%COMPUTERNAME%\ASPNET echo Y|cacls.exe "%PRIVATE_KEY_FILE%" /E /G "%WP_ACCOUNT%":R iisreset pause ------------------------------------------------------------------------- 以上でサーバー側の設定がおわりました。 次は、クライアントの設定です。 ------------------------------------------------------------------------- |
|
投稿日時: 2008-02-07 08:39
次にクライアント側です。
------------------------------------------------------------------------- 1.Windowsフォームプロジェクトの作成 ------------------------------------------------------------------------- [ファイル]→[新規作成]→[プロジェクト] →[Windows]→[Windowsフォームアプリケーション]で作成。 ------------------------------------------------------------------------- 2.WCFサービスの追加 ------------------------------------------------------------------------- [サービス参照の追加]から、WCFホストしているIISのアドレスを移動 サービス名がでてきたら、名前空間をWEBに変更。 ------------------------------------------------------------------------- 3.フォームの編集 ------------------------------------------------------------------------- フォーム上にボタンをひとつ追加して、以下のコードを追加 private void button1_Click(object sender, EventArgs e) { WEB.Service1Client host = new WindowsFormsApplication1.WEB.Service1Client(); try { host.ClientCredentials.UserName.UserName = "test1"; host.ClientCredentials.UserName.Password = "1tset"; MessageBox.Show(host.GetData(123)); host.Close(); } catch (System.Exception ex) { host.Abort(); MessageBox.Show(ex.Message); } finally { } } ------------------------------------------------------------------------- 4.App.Configの編集 ------------------------------------------------------------------------- <system.serviceModel>内に <behaviors> <endpointBehaviors> <behavior name="ClientCredentialsBehavior"> <clientCredentials> <serviceCertificate> <authentication certificateValidationMode="None" /> </serviceCertificate> </clientCredentials> </behavior> </endpointBehaviors> </behaviors> を追加。 また、既存の <client>を以下のように編集する <client> <endpoint address="http://**実際のURL**/Service1.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1" contract="WEB.IService1" behaviorConfiguration="ClientCredentialsBehavior" name="WSHttpBinding_IService1"> <identity> <dns value="localhost" /> </identity> </endpoint> </client> ------------------------------------------------------------------------- 以上で、WCFを利用したカスタム認証が可能になります。 ------------------------------------------------------------------------- |
|
投稿日時: 2008-02-07 08:46
追記。
先のエラー内容について、 「サービス証明書が指定されていません。ServiceCredentials で サービス証明書を指定してください。」 のエラーが発生 →やはり、証明書が必要なので、設定が必要であった。 「System.Security.Cryptography.CryptographicException: キー セットが ありません。」 のエラーが発生 →証明書の秘密キーに関する権限の付与がなかったために発生。 LocalMachine ストアに保存されたサーバー証明書を ASP.NET ワーカー プロセス アカウントでアクセスできるようにしなければならなかった。 |
1