Windows フォームでのより安全なファイルとデータ アクセス
.NET Framework では、アクセス許可を使用してリソースとデータを保護します。 アプリケーションがデータの読み取りまたは書き込みを行うことができる場所は、アプリケーションに付与されるアクセス許可によって異なります。 アプリケーションが部分信頼環境で実行されている場合、データにアクセスできない場合や、データへのアクセス方法を変更する必要がある場合があります。
セキュリティ制限が発生した場合は、2 つのオプションがあります。アクセス許可をアサートするか (アプリケーションに許可されている場合)、または部分的な信頼で動作するように記述された機能のバージョンを使用します。 以降のセクションでは、部分信頼環境で実行されているアプリケーションからのファイル、データベース、およびレジストリへのアクセスを操作する方法について説明します。
手記
既定では、ClickOnce 配置生成ツールは、実行するコンピューターに対して完全信頼を要求するようにこれらの配置をデフォルト設定します。 部分信頼で実行するセキュリティ上の利点を追加する場合は、Visual Studio またはいずれかの Windows SDK ツール (Mage.exe または MageUI.exe) でこの既定値を変更する必要があります。 Windows フォームのセキュリティの詳細と、アプリケーションの適切な信頼レベルを決定する方法については、「Windows フォームの概要の
ファイル アクセス
FileIOPermission クラスは、.NET Framework のファイルとフォルダーへのアクセスを制御します。 既定では、セキュリティ システムは、ローカル イントラネットやインターネット ゾーンなどの部分信頼環境に FileIOPermission を付与しません。 ただし、アプリケーションの設計を変更したり、別の方法を使用してファイルにアクセスしたりする場合、ファイル アクセスを必要とするアプリケーションは、これらの環境で引き続き機能します。 既定では、ローカル イントラネット ゾーンには、同じサイト アクセス権と同じディレクトリ アクセス権を持ち、元のサイトに接続し、インストール ディレクトリから読み取る権限が付与されます。 既定では、インターネット ゾーンには、元のサイトに接続する権限のみが付与されます。
User-Specified ファイル
ファイル アクセス許可がない場合に対処する方法の 1 つは、OpenFileDialog または SaveFileDialog クラスを使用して特定のファイル情報を提供するようにユーザーに求める方法です。 このユーザー操作は、アプリケーションが悪意を持ってプライベート ファイルを読み込んだり、重要なファイルを上書きしたりできないことを保証するのに役立ちます。 OpenFile メソッドと OpenFile メソッドは、ユーザーが指定したファイルのファイル ストリームを開くことで、ファイルの読み取りと書き込みのアクセスを提供します。 また、このメソッドは、ファイルのパスを隠すことによってユーザーのファイルを保護するのにも役立ちます。
手記
これらのアクセス許可は、アプリケーションがインターネット ゾーンとイントラネット ゾーンのどちらにあるかによって異なります。 インターネット ゾーン アプリケーションでは OpenFileDialogのみを使用できますが、イントラネット アプリケーションには無制限のファイル ダイアログアクセス許可があります。
FileDialogPermission クラスは、アプリケーションで使用できるファイル ダイアログ ボックスの種類を指定します。 次の表に、各 FileDialog クラスを使用する必要がある値を示します。
クラス | 必要なアクセス値 |
---|---|
OpenFileDialog | Open |
SaveFileDialog | Save |
手記
OpenFile メソッドが実際に呼び出されるまで、特定のアクセス許可は要求されません。
ファイル ダイアログ ボックスを表示するアクセス許可では、FileDialog、OpenFileDialog、および SaveFileDialog クラスのすべてのメンバーへのフル アクセス権がアプリケーションに付与されません。 各メソッドを呼び出すために必要な正確なアクセス許可については、.NET Framework クラス ライブラリのドキュメントでそのメソッドのリファレンス トピックを参照してください。
次のコード例では、OpenFile メソッドを使用して、ユーザー指定のファイルを RichTextBox コントロールに開きます。 この例では、FileDialogPermission と関連付けられている Open 列挙値が必要です。 この例では、SecurityException を処理して、保存機能を無効にするかどうかを判断する方法を示します。 この例では、Form に ButtonOpen
という名前の Button コントロールと、RtfBoxMain
という名前の RichTextBox コントロールが必要です。
手記
この例では、保存機能のプログラミング ロジックは示されていません。
Private Sub ButtonOpen_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles ButtonOpen.Click
Dim editingFileName as String = ""
Dim saveAllowed As Boolean = True
' Displays the OpenFileDialog.
If (OpenFileDialog1.ShowDialog() = DialogResult.OK) Then
Dim userStream as System.IO.Stream
Try
' Opens the file stream for the file selected by the user.
userStream =OpenFileDialog1.OpenFile()
Me.RtfBoxMain.LoadFile(userStream, _
RichTextBoxStreamType.PlainText)
Finally
userStream.Close()
End Try
' Tries to get the file name selected by the user.
' Failure means that the application does not have
' unrestricted permission to the file.
Try
editingFileName = OpenFileDialog1.FileName
Catch ex As Exception
If TypeOf ex Is System.Security.SecurityException Then
' The application does not have unrestricted permission
' to the file so the save feature will be disabled.
saveAllowed = False
Else
Throw ex
End If
End Try
End If
End Sub
private void ButtonOpen_Click(object sender, System.EventArgs e)
{
String editingFileName = "";
Boolean saveAllowed = true;
// Displays the OpenFileDialog.
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
// Opens the file stream for the file selected by the user.
using (System.IO.Stream userStream = openFileDialog1.OpenFile())
{
this.RtfBoxMain.LoadFile(userStream,
RichTextBoxStreamType.PlainText);
userStream.Close();
}
// Tries to get the file name selected by the user.
// Failure means that the application does not have
// unrestricted permission to the file.
try
{
editingFileName = openFileDialog1.FileName;
}
catch (Exception ex)
{
if (ex is System.Security.SecurityException)
{
// The application does not have unrestricted permission
// to the file so the save feature will be disabled.
saveAllowed = false;
}
else
{
throw ex;
}
}
}
}
手記
Visual C# で、イベント ハンドラーを有効にするコードを必ず追加してください。 前の例のコードを使用して、次のコードはイベント ハンドラーを有効にする方法を示しています。this.ButtonOpen.Click += newSystem.Windows.Forms.EventHandler(this.ButtonOpen_Click);
その他のファイル
アプリケーション設定を保持する必要がある場合など、ユーザーが指定しないファイルの読み取りまたは書き込みが必要になる場合があります。 ローカル イントラネットとインターネット ゾーンでは、アプリケーションにはローカル ファイルにデータを格納するアクセス許可がありません。 ただし、アプリケーションは分離ストレージにデータを格納できます。 分離ストレージは、データが格納される実際のディレクトリの場所を含む、ストアと呼ばれる 1 つ以上の分離ストレージ ファイルを含む抽象データ コンパートメント (特定のストレージの場所ではありません) です。 FileIOPermission などのファイル アクセス許可は必要ありません。代わりに、IsolatedStoragePermission クラスは分離ストレージのアクセス許可を制御します。 既定では、ローカル イントラネットおよびインターネット ゾーンで実行されているアプリケーションは、分離ストレージを使用してデータを格納できます。ただし、ディスク クォータなどの設定は異なる場合があります。 分離ストレージの詳細については、「分離ストレージの
次の例では、分離ストレージを使用して、ストア内のファイルにデータを書き込みます。 この例では、IsolatedStorageFilePermission と DomainIsolationByUser 列挙値が必要です。 この例では、分離ストレージ内のファイルに対する Button コントロールの特定のプロパティ値の読み取りと書き込みを示します。 Read
関数は、アプリケーションの起動後に呼び出され、アプリケーションが終了する前に Write
関数が呼び出されます。 この例では、Read
関数と Write
関数が、MainButton
という名前の Button コントロールを含む Form のメンバーとして存在する必要があります。
' Reads the button options from the isolated storage. Uses Default values
' for the button if the options file does not exist.
Public Sub Read()
Dim isoStore As System.IO.IsolatedStorage.IsolatedStorageFile = _
System.IO.IsolatedStorage.IsolatedStorageFile. _
GetUserStoreForDomain()
Dim filename As String = "options.txt"
Try
' Checks to see if the options.txt file exists.
If (isoStore.GetFileNames(filename).GetLength(0) <> 0) Then
' Opens the file because it exists.
Dim isos As New System.IO.IsolatedStorage.IsolatedStorageFileStream _
(filename, IO.FileMode.Open,isoStore)
Dim reader as System.IO.StreamReader
Try
reader = new System.IO.StreamReader(isos)
' Reads the values stored.
Dim converter As System.ComponentModel.TypeConverter
converter = System.ComponentModel.TypeDescriptor.GetConverter _
(GetType(Color))
Me.MainButton.BackColor = _
CType(converter.ConvertFromString _
(reader.ReadLine()), Color)
me.MainButton.ForeColor = _
CType(converter.ConvertFromString _
(reader.ReadLine()), Color)
converter = System.ComponentModel.TypeDescriptor.GetConverter _
(GetType(Font))
me.MainButton.Font = _
CType(converter.ConvertFromString _
(reader.ReadLine()), Font)
Catch ex As Exception
Debug.WriteLine("Cannot read options " + _
ex.ToString())
Finally
reader.Close()
End Try
End If
Catch ex As Exception
Debug.WriteLine("Cannot read options " + ex.ToString())
End Try
End Sub
' Writes the button options to the isolated storage.
Public Sub Write()
Dim isoStore As System.IO.IsolatedStorage.IsolatedStorageFile = _
System.IO.IsolatedStorage.IsolatedStorageFile. _
GetUserStoreForDomain()
Dim filename As String = "options.txt"
Try
' Checks if the file exists, and if it does, tries to delete it.
If (isoStore.GetFileNames(filename).GetLength(0) <> 0) Then
isoStore.DeleteFile(filename)
End If
Catch ex As Exception
Debug.WriteLine("Cannot delete file " + ex.ToString())
End Try
' Creates the options.txt file and writes the button options to it.
Dim writer as System.IO.StreamWriter
Try
Dim isos As New System.IO.IsolatedStorage.IsolatedStorageFileStream _
(filename, IO.FileMode.CreateNew, isoStore)
writer = New System.IO.StreamWriter(isos)
Dim converter As System.ComponentModel.TypeConverter
converter = System.ComponentModel.TypeDescriptor.GetConverter _
(GetType(Color))
writer.WriteLine(converter.ConvertToString( _
Me.MainButton.BackColor))
writer.WriteLine(converter.ConvertToString( _
Me.MainButton.ForeColor))
converter = System.ComponentModel TypeDescriptor.GetConverter _
(GetType(Font))
writer.WriteLine(converter.ConvertToString( _
Me.MainButton.Font))
Catch ex as Exception
Debug.WriteLine("Cannot write options " + ex.ToString())
Finally
writer.Close()
End Try
End Sub
// Reads the button options from the isolated storage. Uses default values
// for the button if the options file does not exist.
public void Read()
{
System.IO.IsolatedStorage.IsolatedStorageFile isoStore =
System.IO.IsolatedStorage.IsolatedStorageFile.
GetUserStoreForDomain();
string filename = "options.txt";
try
{
// Checks to see if the options.txt file exists.
if (isoStore.GetFileNames(filename).GetLength(0) != 0)
{
// Opens the file because it exists.
System.IO.IsolatedStorage.IsolatedStorageFileStream isos =
new System.IO.IsolatedStorage.IsolatedStorageFileStream
(filename, System.IO.FileMode.Open,isoStore);
System.IO.StreamReader reader = null;
try
{
reader = new System.IO.StreamReader(isos);
// Reads the values stored.
TypeConverter converter ;
converter = TypeDescriptor.GetConverter(typeof(Color));
this.MainButton.BackColor =
(Color)(converter.ConvertFromString(reader.ReadLine()));
this.MainButton.ForeColor =
(Color)(converter.ConvertFromString(reader.ReadLine()));
converter = TypeDescriptor.GetConverter(typeof(Font));
this.MainButton.Font =
(Font)(converter.ConvertFromString(reader.ReadLine()));
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine
("Cannot read options " + ex.ToString());
}
finally
{
reader.Close();
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine
("Cannot read options " + ex.ToString());
}
}
// Writes the button options to the isolated storage.
public void Write()
{
System.IO.IsolatedStorage.IsolatedStorageFile isoStore =
System.IO.IsolatedStorage.IsolatedStorageFile.
GetUserStoreForDomain();
string filename = "options.txt";
try
{
// Checks if the file exists and, if it does, tries to delete it.
if (isoStore.GetFileNames(filename).GetLength(0) != 0)
{
isoStore.DeleteFile(filename);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine
("Cannot delete file " + ex.ToString());
}
// Creates the options file and writes the button options to it.
System.IO.StreamWriter writer = null;
try
{
System.IO.IsolatedStorage.IsolatedStorageFileStream isos = new
System.IO.IsolatedStorage.IsolatedStorageFileStream(filename,
System.IO.FileMode.CreateNew,isoStore);
writer = new System.IO.StreamWriter(isos);
TypeConverter converter ;
converter = TypeDescriptor.GetConverter(typeof(Color));
writer.WriteLine(converter.ConvertToString(
this.MainButton.BackColor));
writer.WriteLine(converter.ConvertToString(
this.MainButton.ForeColor));
converter = TypeDescriptor.GetConverter(typeof(Font));
writer.WriteLine(converter.ConvertToString(
this.MainButton.Font));
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine
("Cannot write options " + ex.ToString());
}
finally
{
writer.Close();
}
}
データベース アクセス
データベースへのアクセスに必要なアクセス許可は、データベース プロバイダーによって異なります。ただし、データ接続を介してデータベースにアクセスできるのは、適切なアクセス許可で実行されているアプリケーションだけです。 データベースにアクセスするために必要なアクセス許可の詳細については、「Code Access Security and ADO.NET」を参照してください。
アプリケーションを部分信頼で実行する必要があるためにデータベースに直接アクセスできない場合は、データにアクセスするための代替手段として Web サービスを使用できます。 Web サービスは、ネットワーク経由でプログラムでアクセスできるソフトウェアの一部です。 Web サービスを使用すると、アプリケーションはコード グループ ゾーン間でデータを共有できます。 既定では、ローカル イントラネットおよびインターネット ゾーン内のアプリケーションには、配信元のサイトにアクセスする権限が付与され、同じサーバーでホストされている Web サービスを呼び出す権限が付与されます。 詳細については、ASP.NET AJAX または Windows Communication Foundation
レジストリ アクセス
RegistryPermission クラスは、オペレーティング システム レジストリへのアクセスを制御します。 既定では、ローカルで実行されているアプリケーションのみがレジストリにアクセスできます。 RegistryPermission は、アプリケーションにレジストリ アクセスを試す権限のみを付与します。オペレーティング システムは引き続きレジストリにセキュリティを適用するため、アクセスが成功するとは限りません。
部分信頼ではレジストリにアクセスできないため、データを格納する他の方法を見つける必要がある場合があります。 アプリケーション設定を格納する場合は、レジストリの代わりに分離ストレージを使用します。 分離ストレージを使用して、他のアプリケーション固有のファイルを格納することもできます。 また、サーバーまたは配信元サイトに関するグローバル アプリケーション情報を格納することもできます。既定では、アプリケーションには配信元サイトにアクセスする権限が付与されるためです。
関連情報を見る
- Windows フォームでのより安全な印刷
- Windows フォーム の追加のセキュリティ考慮事項
- Windows フォームの セキュリティの概要
- Windows フォームのセキュリティ
- Mage.exe (マニフェスト生成および編集ツール)
- MageUI.exe (マニフェスト生成および編集ツール、グラフィカル クライアント)
.NET Desktop feedback