Windows Forms의 파일 및 데이터 액세스 추가 보안
.NET Framework에서는 권한을 통해 리소스와 데이터를 보호합니다. 응용 프로그램이 데이터를 읽거나 쓸 수 있는 위치는 응용 프로그램에 부여된 권한에 따라 다릅니다. 부분 신뢰 환경에서 응용 프로그램을 실행할 때는 데이터에 액세스할 수 없거나 데이터 액세스 방법을 변경해야 할 수도 있습니다.
보안 제한이 있으면 응용 프로그램에 권한이 부여되었다고 간주하고 권한을 어설션하거나 부분 신뢰 환경에서 작동하도록 작성된 버전의 기능을 사용할 수 있습니다. 다음 단원에서는 부분 신뢰 환경에서 실행되는 응용 프로그램에서 파일, 데이터베이스 및 레지스트리에 액세스하는 방법을 설명합니다.
참고
기본적으로 ClickOnce 배포를 생성하는 도구는 이 배포가 실행되는 컴퓨터에서 완전 신뢰를 요청하도록 지정합니다. 부분 신뢰 환경에서 실행될 때의 보안상 이점을 활용하려면 Visual Studio나 Windows SDK(소프트웨어 개발 키트) 도구인 Mage.exe 또는 MageUI.exe 중 하나에서 이 기본값을 변경해야 합니다. Windows Forms 보안에 대한 자세한 내용과 응용 프로그램의 적절한 신뢰 수준을 결정하는 방법에 대한 자세한 내용은 Windows Forms의 보안 개요를 참조하십시오.
파일 액세스
.NET Framework에서는 FileIOPermission 클래스가 파일 및 폴더 액세스를 제어합니다. 기본적으로 보안 시스템에서는 로컬 인트라넷과 인터넷 영역 등의 부분 신뢰 환경에는 FileIOPermission을 부여하지 않습니다. 그러나 응용 프로그램의 디자인을 수정하거나 다른 파일 액세스 방법을 사용하면 파일 액세스가 필요한 응용 프로그램이 이런 환경에서도 여전히 작동할 수 있습니다. 기본적으로 로컬 인트라넷 영역에는 사이트 액세스와 디렉터리 액세스를 동일하게 지정할 수 있는 권한, 원본 사이트에 다시 연결할 수 있는 권한 및 설치 디렉터리에서 읽을 수 있는 권한이 부여됩니다. 기본적으로 인터넷 영역에는 원본 사이트에 다시 연결할 수 있는 권한만 부여됩니다.
사용자 지정 파일
파일 액세스 권한을 가지고 있지 않은 경우 이를 처리하는 한 가지 방법은 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);
기타 파일
응용 프로그램 설정을 유지해야 하는 경우와 같이 사용자가 지정하지 않은 파일을 읽거나 써야 하는 경우가 있습니다. 로컬 인트라넷과 인터넷 영역에서는 로컬 파일에 데이터를 저장할 수 있는 권한이 응용 프로그램에 부여되지 않습니다. 그러나 응용 프로그램에서 격리된 저장소에 데이터를 저장할 수는 있습니다. 격리된 저장소는 구체적인 저장소 위치가 아닌 추상적인 데이터 구획으로, 데이터가 저장된 실제 디렉터리 위치가 포함되어 있으며 저장소라고도 하는 하나 이상의 격리된 저장소 파일을 포함합니다. 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();
}
}
데이터베이스 액세스
데이터베이스 액세스에 필요한 권한은 데이터베이스 공급자에 따라 다르지만 적절한 권한을 사용하여 실행되는 응용 프로그램만 데이터 연결을 통해 데이터베이스에 액세스할 수 있습니다. 데이터베이스에 액세스하는 데 필요한 권한에 대한 자세한 내용은 코드 액세스 보안 및 ADO.NET를 참조하십시오.
부분 신뢰 환경에서 응용 프로그램을 실행하려고 하기 때문에 데이터베이스에 직접 액세스할 수 없으면 대신 웹 서비스를 사용하여 데이터에 액세스할 수 있습니다. 웹 서비스는 네트워크를 통해 프로그래밍 방식으로 액세스할 수 있는 일종의 소프트웨어입니다. 웹 서비스를 사용하면 응용 프로그램에서 코드 그룹 영역 간에 데이터를 공유할 수 있습니다. 기본적으로 로컬 인트라넷과 인터넷 영역의 응용 프로그램에는 원본 사이트에 액세스할 수 있는 권한이 부여되므로 동일한 서버에 호스팅되는 웹 서비스를 호출할 수 있습니다. 자세한 내용은 ASP.NET AJAX and Web Services 또는 Windows Communication Foundation을 참조하십시오.
레지스트리 액세스
RegistryPermission 클래스가 운영 체제 레지스트리에 대한 액세스를 제어합니다. 기본적으로 로컬에서 실행되고 있는 응용 프로그램만 레지스트리에 액세스할 수 있습니다. RegistryPermission은 응용 프로그램에 레지스트리 액세스를 시도할 수 있는 권한만 부여할 뿐이며 운영 체제에서 레지스트리에 보안을 적용하기 때문에 해당 액세스가 성공한다는 보장은 없습니다.
부분 신뢰 환경에서는 레지스트리에 액세스할 수 없으므로 다른 방법으로 데이터를 저장해야 합니다. 응용 프로그램 설정을 저장할 때는 레지스트리가 아닌 격리된 저장소를 사용합니다. 격리된 저장소는 기타 응용 프로그램 관련 파일을 저장할 때도 사용할 수 있습니다. 기본적으로 원본 사이트에 액세스할 수 있는 권한이 응용 프로그램에 부여되므로 원본 서버나 원본 사이트에 대한 전역 응용 프로그램 정보를 저장할 수도 있습니다.
참고 항목
참조
MageUI.exe (매니페스트 생성 및 편집 도구, 그래픽 클라이언트)