Windows フォームにおけるファイルおよびデータへのより安全なアクセス
.NET Framework では、アクセス許可を使用してリソースおよびデータを保護しています。 特定の場所でアプリケーションがデータを読み書きできるかどうかは、アプリケーションに与えられているアクセス許可によって異なります。 部分信頼環境でアプリケーションが動作している場合は、データにアクセスできないか、またはアクセス方法の変更が必要になる場合があります。
セキュリティ上の制限がある場合、2 つのオプションがあります。アクセス許可を与える方法 (アプリケーションにアクセス許可が認められている場合)、または部分信頼で機能するように記述した機能のバージョンを使用する方法です。 以下のセクションでは、部分信頼環境で動作しているアプリケーションからファイル、データベース、およびレジストリにアクセスする方法について説明しています。
注意
ClickOnce 配置を生成するツールは、既定で、実行コンピューターに完全な信頼を要求する配置を行います。 部分信頼で実行してセキュリティを強化する場合、Visual Studio または Windows Software Development Kit (SDK) ツールのいずれか (Mage.exe または MageUI.exe) を使用し、この既定を変更する必要があります。 Windows フォームのセキュリティ、およびアプリケーションの適切な信頼レベルを決定する方法の詳細については、「Windows フォームのセキュリティの概要」を参照してください。
ファイル アクセス
FileIOPermission クラスは、.NET Framework でのファイルおよびフォルダーへのアクセスを制御します。 既定では、セキュリティ システムは [イントラネット] ゾーンや [インターネット] ゾーンのような部分信頼環境には FileIOPermission を許可しません。 ただし、そのような環境でも、アプリケーションのデザインを変更したり、別のメソッドを使用してファイルにアクセスしたりすると、ファイルへのアクセスを必要とするアプリケーションが機能できます。 既定では、[イントラネット] ゾーンは、その元のサイトへの接続とそのインストール ディレクトリからの読み取りを実行する、同じサイトおよびディレクトリへのアクセスの権限が与えられます。 [インターネット] ゾーンには、既定でその元のサイトに接続する権限しか与えられません。
ユーザー指定ファイル
ファイル アクセス許可が得られない場合の対処法の 1 つは、OpenFileDialog クラスまたは SaveFileDialog クラスを使用して、具体的なファイル情報を提供するようユーザーに求めることです。 このユーザーとの対話により、アプリケーションが悪意のあるプライベート ファイルを読み込んだり重要なファイルを上書きしたりできないようになります。 OpenFile メソッドと OpenFile メソッドは、ユーザーが指定したファイルに対してファイル ストリームを開くことにより、読み取りおよび書き込みのファイル アクセスを提供します。 また、これらのメソッドは、ファイルのパスを隠すことで、ユーザーのファイルを保護することもできます。
注意
これらのアクセス許可は、アプリケーションがインターネット ゾーンにあるかイントラネット ゾーンにあるかによって異なります。 インターネット ゾーンのアプリケーションは、OpenFileDialog のみを使用できますが、イントラネット ゾーンのアプリケーションの場合、ファイル ダイアログのアクセス許可は制限されていません。
FileDialogPermission クラスは、アプリケーションが使用できるファイル ダイアログ ボックスの種類を指定します。 各 FileDialog クラスを使用するために必要な値を次の表に示します。
クラス |
必要なアクセス値 |
---|---|
注意
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 関数はアプリケーションが終了する前に呼び出されます。 この例では、MainButton という Button コントロールを含む Form のメンバーとして、Read 関数と Write 関数が存在する必要があります。
' 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();
}
}
データベース アクセス
データベースへのアクセスに必要なアクセス許可は、データベース プロバイダーによって異なります。ただし、適切なアクセス許可で動作しているアプリケーションだけがデータ接続を通じてデータベースにアクセスできます。 データベースにアクセスするために必要なアクセス許可の詳細については、「コード アクセス セキュリティと ADO.NET」を参照してください。
部分信頼でアプリケーションを実行しているためにデータベースに直接アクセスできない場合は、代わりの手段として、Web サービスを使用してデータにアクセスできます。 Web サービスは、プログラムからネットワーク経由でアクセスできるソフトウェアです。 Web サービスを使用すると、アプリケーションはコード グループ ゾーン間でデータを共有できます。 既定では、[イントラネット] ゾーンおよび [インターネット] ゾーンのアプリケーションは、その元のサイトにアクセスする権限を与えられているので、同じサーバーでホストされている Web サービスを呼び出すことができます。 詳細については、「Web Services in ASP.NET AJAX」または「Windows Communication Foundation」を参照してください。
レジストリへのアクセス
RegistryPermission クラスは、オペレーティング システム レジストリへのアクセスを制御します。 既定では、ローカルに動作しているアプリケーションだけがレジストリにアクセスできます。 RegistryPermission は、アプリケーションにレジストリ アクセスを試行する権限のみを許可します。アクセスが成功することは保証していません。これは、オペレーティング システムがレジストリでセキュリティを適用しているためです。
部分信頼ではレジストリにアクセスできないため、データを格納する他の方法を探す必要があります。 アプリケーション設定を格納する場合は、レジストリではなく分離ストレージを使用します。 分離ストレージは、アプリケーション固有のその他のファイルを格納する場合にも使用できます。 また、アプリケーションには既定でその元のサイトへのアクセス権限が与えられるため、元のサーバーまたはサイトに関するグローバルなアプリケーション情報も格納できます。
参照
参照
MageUI.exe (マニフェスト生成および編集ツールのグラフィカル クライアント)
概念
Windows フォームのセキュリティに関するその他の考慮事項