アーカイブ

Archive for 2006年2月

web.configの暗号化

2006年2月23日 1件のコメント

web.configにはデータベースへの接続文字列など、ユーザ名とパスワードといった情報を記述しなければいけない場合があります。こういった重要な情報をテキストファイルに平文で記述していることに不安を覚える人もいるでしょう。
ASP.NET 2.0ではaspnet_regiis.exeを利用してweb.configを暗号化することができるようになりました。この暗号化した情報はASP.NETによって自動的に複合化されて読み取られるので、開発の終了後、運用サーバに配置する時点でweb.configの暗号化を行うだけの手間しか必要ではありません。

実際の暗号化の手順をみていきましょう。

○運用サーバ上で暗号化を行う

運用サーバの管理を自分で行っているのであれば、運用サーバ上で暗号化を行うのが一番簡単です。
サーバ上のコンソールから以下のようにコマンドを入力します。

aspnet_regiis -pef "暗号化するセクション" web.configがあるフォルダ

aspnet_regiis.exeは通常 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 フォルダに存在しています。
暗号化はセクションごとに行います。暗号化するセクションには、自分が利用しているセクションに合わせて以下のように指定します。

【例】
データベースへの接続:"connectionStrings"
アプリケーション設定:"appSettings"
smtpクライアント設定:"system.net/mailSettings/smtp"

web.configがあるフォルダには、たとえば「c:\Inetpub\wwwroot\website1」のように物理的なフォルダを指定します。

以下の内容のweb.configファイルをCドライブのルートにおいて実験してみます。

——————————————————————–
<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <remove name="LocalSqlServer"/>
    <add name="LocalSqlServer"
          connectionString="server=サーバ名;uid=ユーザID;pwd=パスワード;Trusted_Connection=no;database=データベース名"
          providerName="System.Data.SqlClient"/>
  </connectionStrings>
</configuration>
——————————————————————–

実行するコマンドは次のようになります。

> aspnet_regiis -pef "connectionStrings" c:\

これによって、web.configは以下のように書き換えられます。

——————————————————————–
<?xml version="1.0"?>
<configuration>
  <connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
      xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <KeyName>Rsa Key</KeyName>
          </KeyInfo>
          <CipherData>
            <CipherValue>mUBXZ2ToYw36KCzKafXkmoFRU144s2FHbs9BSdRauJAbH0b4rM2mv3Mjlmx+lolwEM6Ay0HP4XQnsXSt2/qznSFyZ7L9j1XpzdK02Cj8hLoFePQjFmbQstZ+I3ZY44OE8LfGPGVqkGjJgxoG4nJ8LfDF6PZTOHg/HXZ3ppbFdQk=</CipherValue>
          </CipherData>
        </EncryptedKey>
      </KeyInfo>
      <CipherData>
        <CipherValue>F+AKN5rRXFYHf03QWXW7/HgxXjWePM3akXoZQ6PEKntYW4QSOVBr/nZjBBb9HynOXyCELhqyXqAsQA8pWYVEAYkmgS2y+yoU3R3P8NFjMl/K9ZbuYhVoSyuHFmwDmF0Z+JjqN1FCRYw+oaXhwEm3swcoKe/192ci3TTM47+AeSKCJiQuOTS4fqggl6oFaDxzKbUU4rE6Jro1P42/uU8HSHMOfqwt0YA4NKW06uoMMOfjUqzrcYmLasA/67vAy1B4hDeCSt5hodZT2FBpRPT8JLiR5/ZN0wDJLEAMiFP98lbhwFBWnCI0ZBoh2b/jW3aJ/AZ7XrigXCRBXJhyFYh9HQOEumroGzul2if7/Gpn5D8lEzOIbNRrZivuOA+tMg1Q</CipherValue>
      </CipherData>
    </EncryptedData>
  </connectionStrings>
</configuration>
——————————————————————–

なお、暗号化したデータを複合化して平文に戻すことも可能です。
この場合、-pef オプションの代わりに -pdf オプションを利用します。

> aspnet_regiis -pdf "connectionStrings" c:\

○運用サーバとは別の開発マシンで暗号化を行う

運用サーバの管理権限が開発者にない場合、暗号化のためのキーを運用サーバと開発マシンとで合わせる必要があります。このため若干手順が増えます。

◆運用サーバ上の作業◆

・キーを作成する

運用サーバ上にまず利用するキーを作成します。

> aspnet_regiis -pc "CustomKey" -exp

このように実行することで他のマシンへの持ち出し(エクスポート)が可能なCustomKeyという名前のキーを作成できます。
キーは C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys フォルダに作成されます。

・キーに読み取り権限を追加する

キーはNTFSのアクセス権で管理されています。ASP.NETの実行ユーザがキーを読み取れるようにアクセス権を付与する必要があります。

> aspnet_regiis -pa "CustomKey" "NT Authority\Network Service"

このように実行すると、Windows Server 2003上のASP.NETの実行ユーザにCustomKeyの読み取り権限が付与されます。

・キーをエクスポートする

キーはXMLファイルにエクスポートすることでやりとりすることができます。

> aspnet_regiis -px "CustomKey" "C:\CustomKey.xml" -pri

このように実行すると、CustomKey.xmlというファイルにCustomKeyがエクスポートされます。
-priオプションは開発マシン上で暗号化だけでなく複合化もできるようにするために必要なオプションです。
開発マシンにはこのCustomKey.xmlファイルを渡します。

◆開発マシン上の作業◆

・キーをインポートする

運用サーバ上で作成されたCustomKey.xmlファイルを開発マシン上に登録します。

> aspnet_regiis -pi "CustomKey" "C:\CustomKey.xml"

このように実行することで、CustomKeyが開発マシン上にも作成されます。

・キーに読み取り権限を追加する

開発マシン上で、VS2005の開発用Webサーバを用いてテストしている場合はこの作業は必要ありません。
開発マシンでIISからWebアプリケーションのテストを行っている場合は、ASP.NETの実行ユーザにキーの読み取り権限を与える必要があります。

> aspnet_regiis -pa "CustomKey" "ASPNET"

このように実行すると、Windows XP上のASP.NETの実行ユーザにCustomKeyの読み取り権限が付与されます。

・web.configを修正する

web.configの暗号化にCustomKeyを利用するためには、web.configの中にその設定を記述する必要があります。
以下の記述をweb.configに追加します

<configProtectedData>
  <providers>
    <add keyContainerName="CustomKey"
         useMachineContainer="true"
         description="Uses RsaCryptoServiceProvider to encrypt and decrypt"
         name="CustomProvider"
         type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral,  PublicKeyToken=b03f5f7f11d50a3a" />
  </providers>
</configProtectedData>

keyContainerNameには利用するキーの名前を設定します。
また、nameに設定した値を実際の暗号化時に利用します。
web.configはたとえば以下のようになります。

——————————————————————–
<?xml version="1.0"?>
<configuration>
  <configProtectedData>
    <providers>
      <add keyContainerName="CustomKey"
           useMachineContainer="true"
           description="Uses RsaCryptoServiceProvider to encrypt and decrypt"
           name="CustomProvider"
           type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral,  PublicKeyToken=b03f5f7f11d50a3a" />
    </providers>
  </configProtectedData>
  <connectionStrings>
    <remove name="LocalSqlServer" />
    <add name="LocalSqlServer" connectionString="server=サーバ名;uid=ユーザID;pwd=パスワード;Trusted_Connection=no;database=データベース名"
      providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>
——————————————————————–

・web.configを暗号化する

> aspnet_regiis -pdf "connectionStrings" c:\ -prov "CustomProvider"

このように、web.confg内に設定したプロバイダのnameを用いて暗号化を行います。
web.configは以下のようになります。

——————————————————————–
<?xml version="1.0"?>
<configuration>
  <configProtectedData>
    <providers>
      <add keyContainerName="CustomKey"
           useMachineContainer="true"
           description="Uses RsaCryptoServiceProvider to encrypt and decrypt"
           name="CustomProvider"
           type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral,  PublicKeyToken=b03f5f7f11d50a3a" />
    </providers>
  </configProtectedData>
  <connectionStrings configProtectionProvider="CustomProvider">
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
      xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <KeyName>Rsa Key</KeyName>
          </KeyInfo>
          <CipherData>
            <CipherValue>OJ5n7dHLLxwIQHGwaSMSgZhlXO4tlCkBZ8nEQ78zGlwqSylVKmGTK/BLf3MqGAt1Oigmq/Q18fX0Ux2458uhUA8N4e4hPQGr51fSf0bvLzA7GF01u7xYhy+2jngz9lOORMzPx0zw+RzIg0e+4AoMGz27RJP9r/mW2RHmXXqor4I=</CipherValue>
          </CipherData>
        </EncryptedKey>
      </KeyInfo>
      <CipherData>
        <CipherValue>Z+enXyXAOustA2SVWJaE36Ye16muFVv68hAsQHP1Rp+D7CVc56r1GzoLWX1ITUj0ZBVb+TXnxVpy50qHf62JaqZFfaKv6HIDv9NOTrsVegXfO3MSV9zlbFaO6SqKUlUFChs4icfxPiM1oAn2rJ4C8nhiu34TFgdE3FqiTJhTQm28YqTTv3Ax6zak8QxtkBl82n+GT4KXI568OZwHZsekTMsUZYuEgk1KEORI2AehWnmqyLrmssjwXRvcnXQFsE4v8tNg+hiiTeeI0hOxkZRuO/qXx7rBUIr/6ykW/sunIcdWZ5QoagRTU/REy0uPuLqtc2spaBUcgVgZ90bPawfBCqN2haFGlV+/OsBjyXXiWjfTw6a0M/jyeovv72ZsSy9p</CipherValue>
      </CipherData>
    </EncryptedData>
  </connectionStrings>
</configuration>
——————————————————————–

このようにして作成したweb.confgはそのまま運用サーバ上に配置して利用することができます。

 

参考:
保護された構成を使用した構成情報の暗号化
http://msdn2.microsoft.com/ja-jp/library/53tyfkaw.aspx

How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA
http://channel9.msdn.com/wiki/default.aspx/Channel9.HowToEncryptConfigurationSectionsUsingRsaInAspNet20

カテゴリー:.NET, ASP.NET 備忘録

ページ間ポスティングの仕組み

※以下の内容は多分に推測を含んでいます。
間違いがあることに気づいた場合は修正を行います。

ASP.NET 2.0ではページ間ポスティングという機能が導入され、いままでちょっと面倒だったページを遷移したときのデータの引渡しがだいぶ楽になりました。
ページ間ポスティングの使い方は以下のページによくまとめられています。

[@IT]異なるWebフォームにポスト・データを送信するには?
http://www.atmarkit.co.jp/fdotnet/dotnettips/406asppostback1/asppostback1.html

[@IT]ページ間ポストバックでポスト元ページの情報に簡単にアクセスするには?
http://www.atmarkit.co.jp/fdotnet/dotnettips/409asppostback2/asppostback2.html

このページ間ポスティングがどうやって実現されているかを調べてみました。調べるきっかけになったのは実は上記の最初の記事です。

当初、ページ間ポスティングの機能は、

  • ポストバック→Server.Transfer

がベースになって実現されていると考えていました。
ですが、最初の記事をみるとわかるとおり、遷移後のページでブラウザのアドレス欄にはきちんと遷移後のURLが表示されています。Server.Transferを利用していたのなら、ページが遷移したときもURLの表示はそのままで変わることはありません。これはブラウザ上のアドレス欄はブラウザがアクセスしたURLそのものであり、サーバ上でTransferによって表示するページが変えられたとしてもブラウザがそれを判別してアドレス欄に反映するといったことはできないためです。
では、遷移後にURLがきちんと書き換わるページ間ポスティングでは何が起きているのでしょうか。

仕掛けのひとつはJScriptでした。
ボタンにPostBackUrlを記述している場合、このボタンのクリック時に、ボタンが含まれているFormタグのsubmit先がスクリプトによってPostBackUrlに置き換えられます。つまり、クライアント側でスクリプトが動くことによって動的にsubmit先を変更しているわけです。
ブラウザは置き換えられたURLにアクセスしにいきますから、アドレス欄にはきちんと遷移後のURLが表示されます。

アドレスの謎は解けました。ここで新たな謎となってくるのが、PreviousPageの存在です。
Transferを使っている場合、PreviousPageが存在していることは理解できます。Transferを利用しているときは、遷移前のページのインスタンスでTransferメソッドが呼ばれ、遷移後のページのインスタンスが生成されます。この時点でサーバ上には遷移前のページのインスタンスと遷移後のページのインスタンスの両方が存在していることになります。
2つのページのインスタンスが同時にサーバ上に存在していますから、遷移後のページのインスタンスを生成するときにそのPreviousPageとして遷移前のページのインスタンスを設定しているのだろうという推測が成り立ちます。

しかし、ページ間ポスティングの場合、最初からブラウザが遷移後のURLにアクセスしにいくのですから、サーバ側には遷移後のページのインスタンスしか生成されないはずです。PreviousPageはどうやって生成されるのでしょうか。。。

もう一度遷移前のページのHTMLをじっくり眺めてみます。
そこで気になるが"__PREVIOUSPAGE"という名前がついたInputタグです。

ここからはまったくのあてずっぽうになりますが、ASP.NETは"__PREVIOUSPAGE"という名前のデータを受け取った場合、たぶんそのデータ中に含まれるであろうクラス名から遷移前のページのインスタンスを生成し、PreviousPageとして設定するのではないでしょうか。
通常、ASP.NETはPOST形式でデータを受け取る(POSTBACK)と、そのURLからどのページのインスタンスを生成するかを選択し、POSTされたデータをそのインスタンスに埋め込んでいく、という作業を行っています。
"__PREVIOUSPAGE"というデータがある場合は、まずURLからページのインスタンスを生成する。その後"__PREVIOUSPAGE"のデータに含まれるページを選択して別のインスタンスを生成し、POSTされたデータは後から生成したインスタンスに埋め込んで、URLで指定されたページのPreviousPageとして設定する。たぶんこのような処理が行われているのではないでしょうか。

自分としてはこれで一応の説明はつく、と考えています。

カテゴリー:.NET, ASP.NET 備忘録

レンタルサーバでログインコントロールを利用する

ここでは私が借りているcervi上でASP.NET 2.0のログインコントロールを利用するための手順を記述しています。
他のレンタルサーバでも同様の手順で設定ができると思いますが、サーバの各種設定やその設定を確認する方法については利用されているレンタルサーバの管理者にお問い合わせください。

○事前の確認

・ASP.NET 2.0が利用可能であること
      -cerviでは管理者に連絡して2.0が利用できるようにしてもらう必要があります。

・SQL Serverが利用可能であること
      -cerviではSQL Server 2000が標準で利用できるようになっています。

・データベース名、接続文字列を確認しておくこと
      -cerviでは接続文字列をユーザの設定情報にログインして確認できます。

・データベースに対してSQL クエリを発行できること
      -cerviではSQL Server 管理画面からデータベースに接続してクエリを発行することが可能です。

 

○SQL スクリプトを作成する

ログインコントロールを利用するには、利用しているデータベースにコントロールが必要とするテーブル、ビュー、ストアドプロシージャが含まれていればいいわけです。
.NET Framework 2.0に含まれるaspnet_regsql.exeツールを利用すると、これらのテーブル等を作成してくれるSQL スクリプトを手にいれることができます。

aspnet_regsql.exe -sqlexportonly ファイル名 -A all -d データベース名

このようにオプションをつけて実行すれば、指定したファイルにSQL スクリプトが書き込まれます。
このとき注意する点としては、データベース名を間違えないように入力することだけです。
aspnet_regsql.exeは標準的なインストールでは c:\Windows\Microsoft.NET\Framework\v2.0.50727\ フォルダに存在しています。

 

○SQL スクリプトを実行する

cerviのSQL Server 管理画面からデータベースに接続し、クエリアナライザツールを使って上記で取得したSQL スクリプトを実行します。
このときデータベース内に以下のオブジェクトが作成されます。

テーブル

aspnet_Applications
aspnet_Membership
aspnet_Paths
aspnet_PersonalizationAllUsers
aspnet_PersonalizationPerUser
aspnet_Profile
aspnet_Roles
aspnet_SchemaVersions
aspnet_Users
aspnet_UsersInRoles
aspnet_WebEvent_Events

ビュー

vw_aspnet_Applications
vw_aspnet_MembershipUsers
vw_aspnet_Profiles
vw_aspnet_Roles
vw_aspnet_Users
vw_aspnet_UsersInRoles
vw_aspnet_WebPartState_Paths
vw_aspnet_WebPartState_Shared
vw_aspnet_WebPartState_User

ストアドプロシージャ

aspnet_AnyDataInTables
aspnet_Applications_CreateApplication
aspnet_CheckSchemaVersion
aspnet_Membership_ChangePasswordQuestionAndAnswer
aspnet_Membership_CreateUser
aspnet_Membership_FindUsersByEmail
aspnet_Membership_FindUsersByName
aspnet_Membership_GetAllUsers
aspnet_Membership_GetNumberOfUsersOnline
aspnet_Membership_GetPassword
aspnet_Membership_GetPasswordWithFormat
aspnet_Membership_GetUserByEmail
aspnet_Membership_GetUserByName
aspnet_Membership_GetUserByUserId
aspnet_Membership_ResetPassword
aspnet_Membership_SetPassword
aspnet_Membership_UnlockUser
aspnet_Membership_UpdateUser
aspnet_Membership_UpdateUserInfo
aspnet_Paths_CreatePath
aspnet_Personalization_GetApplicationId
aspnet_PersonalizationAdministration_DeleteAllState
aspnet_PersonalizationAdministration_FindState
aspnet_PersonalizationAdministration_GetCountOfState
aspnet_PersonalizationAdministration_ResetSharedState
aspnet_PersonalizationAdministration_ResetUserState
aspnet_PersonalizationAllUsers_GetPageSettings
aspnet_PersonalizationAllUsers_ResetPageSettings
aspnet_PersonalizationAllUsers_SetPageSettings
aspnet_PersonalizationPerUser_GetPageSettings
aspnet_PersonalizationPerUser_ResetPageSettings
aspnet_PersonalizationPerUser_SetPageSettings
aspnet_Profile_DeleteInactiveProfiles
aspnet_Profile_DeleteProfiles
aspnet_Profile_GetNumberOfInactiveProfiles
aspnet_Profile_GetProfiles
aspnet_Profile_GetProperties
aspnet_Profile_SetProperties
aspnet_RegisterSchemaVersion
aspnet_Roles_CreateRole
aspnet_Roles_DeleteRole
aspnet_Roles_GetAllRoles
aspnet_Roles_RoleExists
aspnet_Setup_RemoveAllRoleMembers
aspnet_Setup_RestorePermissions
aspnet_UnRegisterSchemaVersion
aspnet_Users_CreateUser
aspnet_Users_DeleteUser
aspnet_UsersInRoles_AddUsersToRoles
aspnet_UsersInRoles_FindUsersInRole
aspnet_UsersInRoles_GetRolesForUser
aspnet_UsersInRoles_GetUsersInRoles
aspnet_UsersInRoles_IsUserInRole
aspnet_UsersInRoles_RemoveUsersFromRoles
aspnet_WebEvent_LogEvent

ロール

aspnet_Membership_FullAccess
aspnet_Membership_BasicAccess
aspnet_Membership_ReportingAccess
aspnet_Profile_FullAccess
aspnet_Profile_BasicAccess
aspnet_Profile_ReportingAccess
aspnet_Roles_FullAccess
aspnet_Roles_BasicAccess
aspnet_Roles_ReportingAccess
aspnet_Personalization_FullAccess
aspnet_Personalization_BasicAccess
aspnet_Personalization_ReportingAccess
aspnet_WebEvent_FullAccess

もしCommunity ServerやDotNetNukeを利用している場合、ここで作成されるオブジェクトと同名のオブジェクトが利用されているため、このSQL スクリプトを実行するとCommunity Server、DotNetNukeが動かなくなる可能性があります。
そのほかのアプリケーションでも事前に手元のマシンで動作を確認しておく必要はあるでしょう。

 

○web.configで利用するデータベースを指定する

web.configに以下のconnectionStrings設定を追加します。

  <connectionStrings>
        <remove name="LocalSqlServer"/>
        <add name="LocalSqlServer"
          connectionString="server=サーバ名;uid=ユーザID;pwd=パスワード;Trusted_Connection=no;database=データベース名"
          providerName="System.Data.SqlClient"/>
  </connectionStrings>

ログインコントロールは標準でLocalSqlServerという名前で指定されたデータベースを見に行くようになっています。
上記の設定はこれを上書きします。
connectionStringの部分はcerviのユーザの設定情報で確認したものに置き換えてください。
サーバ名、ユーザ名、パスワード、データベース名といった値は設定情報にきちんと含まれています。

これだけの作業でログインコントロールが利用できるようになります。

 

○もしデータベースをきれいにしたいと思ったら

上記のテーブル、ビュー、ストアドプロシージャ、ロールをすべて削除したい、という場合にはaspnet_regsql.exeツールで削除用のSQL スクリプトを生成します。

aspnet_regsql.exe -sqlexportonly ファイル名 -R all -d データベース名

ここで作成されるSQL スクリプトをデータベースに対して実行すればOKです。

カテゴリー:.NET, ASP.NET 備忘録