Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)

음... 요즘 devpia에서 Q&A를 하다 보니, 다소 기초적인 내용들을 올리게 되는군요. ^^

그나저나, 너무 빈번한 질문들에 대해서 매번 타자 치기도 그렇고, 간단한 말로 끝내는 것도 질문한 분께 예의가 아닌 것 같아서, 아예 이런 식으로 제 홈피에 정리해 봅니다.

암튼, 아래와 같은 오류가 나는 경우가 있습니다. 이런 부분은 사실 .NET 보안과 Windows의 보안이 다르기 때문에 발생하게 됩니다.


'/KR_KORITECH_03_31' 응용 프로그램에 서버 오류가 있습니다.


레지스트리 키 HKEY_CLASSES_ROOT\... 에 대한 액세스가 거부되었습니다.

설명: 현재 웹 요청을 실행하는 동안 처리되지 않은 예외가 발생했습니다. 스택 추적을 검토하여 발생한 오류 및 코드에서 오류가 발생한 위치에 대한 자세한 정보를 확인하십시오.

예외 정보: System.UnauthorizedAccessException: 레지스트리 키 HKEY_CLASSES_ROOT\... 에 대한 액세스가 거부되었습니다.

ASP.NET에는 요청한 리소스에 액세스할 권한이 없습니다. ASP.NET 요청 ID에 리소스 액세스 권한을 부여하십시오. ASP.NET에는 응용 프로그램이 가장하지 않을 때 사용되는 기본 프로세스 ID(일반적으로 IIS 5에서는 {MACHINE}\ASPNET, IIS 6에서는 Network Service)가 있습니다. 응용 프로그램이 <identity impersonate="true"/>를 통해 가장하고 있는 경우에는 ID가 익명 사용자(일반적으로 IUSR_MACHINENAME) 또는 인증된 요청 사용자가 됩니다.

파일에 대한 쓰기 권한을 ASP.NET에 부여하려면 탐색기에서 파일을 마우스 오른쪽 단추로 클릭하고 [속성]을 선택한 다음 [보안] 탭을 선택합니다. [추가]를 클릭하여 적절한 사용자나 그룹을 추가합니다. ASP.NET 계정을 강조 표시한 다음 원하는 액세스를 선택합니다.

소스 오류:

줄 200:			string chk5="";
줄 201:
줄 202:			using (....FileUpload fileUpload = new ....FileUpload())
줄 203:			{
줄 204:

소스 파일: c:\inetpub\wwwroot\kr_koritech_03_31\admin\pr\pr_news_write.aspx.cs    줄: 202

스택 추적:

[UnauthorizedAccessException: 레지스트리 키 HKEY_CLASSES_ROOT\... 에 대한 액세스가 거부되었습니다.]
   Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str) +74
   Microsoft.Win32.RegistryKey.CreateSubKey(String subkey) +503
   System.Runtime.InteropServices.RegistrationServices.RegisterManagedType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion) +216
   System.Runtime.InteropServices.RegistrationServices.RegisterAssembly(Assembly assembly, AssemblyRegistrationFlags flags) +258
   System.EnterpriseServices.RegistrationDriver.ClassicRegistration(Assembly asm)

[RegistrationException: 'TestModule.NET, Version=3.0.3.0, Culture=neutral, PublicKeyToken=d71d611ccd9cc3c0' 어셈블리를 등록하지 못했습니다.]
   System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +264
   System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +877
   System.EnterpriseServices.RegistrationHelperTx.InstallAssemblyFromConfig(RegistrationConfig& regConfig, Object sync)
   System.EnterpriseServices.RegistrationHelper.TryTransactedInstall(RegistrationConfig regConfig)
   System.EnterpriseServices.RegistrationHelper.InstallAssemblyFromConfig(RegistrationConfig& regConfig)
   System.EnterpriseServices.RegistrationHelper.InstallAssembly(String assembly, String& application, String partition, String& tlb, InstallationFlags installFlags)
   System.EnterpriseServices.RegistrationHelper.InstallAssembly(String assembly, String& application, String& tlb, InstallationFlags installFlags)
   System.EnterpriseServices.RegistrationHelper.System.EnterpriseServices.Thunk.IThunkInstallation.DefaultInstall(String asm)
   System.EnterpriseServices.Thunk.Proxy.RegisterAssembly(Assembly assembly)
   System.EnterpriseServices.Thunk.Proxy.LazyRegister(Guid id, Type serverType, Boolean checkCache)
   System.EnterpriseServices.Thunk.Proxy.CoCreateObject(Type serverType, Boolean bQuerySCInfo, Boolean& bIsAnotherProcess, String& uri)
   System.EnterpriseServices.ServicedComponentProxyAttribute.CreateInstance(Type serverType)
   System.Runtime.Remoting.Activation.ActivationServices.IsCurrentContextOK(Type serverType, Object[] props, Boolean bNewObj) +74
   koritech.admin.pr.pr_news_write.InsertData() in c:\inetpub\wwwroot\kr_koritech_03_31\admin\pr\pr_news_write.aspx.cs:202
   koritech.admin.pr.pr_news_write.ImageButton1_Click(Object sender, ImageClickEventArgs e) in c:\inetpub\wwwroot\kr_koritech_03_31\admin\pr\pr_news_write.aspx.cs:340
   System.Web.UI.WebControls.ImageButton.OnClick(ImageClickEventArgs e)
   System.Web.UI.WebControls.ImageButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
   System.Web.UI.Page.ProcessRequestMain()


버전 정보: Microsoft .NET Framework 버전:1.1.4322.2032; ASP.NET 버전:1.1.4322.2032 SP.NET Version:1.1.4322.2300

위의 오류 화면은, 한마디로 .NET COM+ 개체가 레지스트리에 자신을 등록해야 하는데 해당 레지스트리 키를 만들 수 있는 권한이 없다는 것입니다. 아시는 것처럼, 일반적으로 Registry는 상당히 중요한 시스템 리소스입니다. 아마도 이 글 읽으시는 분들 중에는 레지스트리를 잘못 편집했다가 시스템이 엉망이 된 경우도 있으실 텐데요. 따라서, 레지스트리를 함부로 편집하지 못하도록 레지스트리 자체에도 Win32 보안이 적용되어져 있습니다.

실제로 COM+ 개체의 경우, 일반적으로 HKEY_CLASSES_ROOT 하위에 자신을 등록하려고 하는데요. 아래의 그림에서 보는 것처럼, 보안이 제법 강력하게 적용되어져 있습니다.

HKEY_CLASSES_ROOT 보안

살펴 보시면, "쓰기 권한"은 "Administrators", "SYSTEM"만이 가능하며, 나머지는 읽기 권한일 뿐입니다.

자, 이제 문제가 분명해 진것 같습니다. "액세스가 거부되었습니다."가 나오는 원인은 ASP.NET 작업자 프로세스가 (등록 코드를 실행하는 스레드까지도) "Administrators", "SYSTEM"에 속해 있지 않기 때문에 발생하는 것입니다.

그렇다면, 답은 2가지가 있을 수 있겠습니다.
첫 번째, HKEY_CLASSES_ROOT 권한에 현재의 ASP.NET 작업자 프로세스의 계정을 추가하는 것입니다. 해당 계정은 "작업관리자" 등을 통해서 확인할 수 있지요. 대개의 경우, IIS 5.0에서는 "ASPNET" 계정이고, IIS 6.0에서는 "Network Service" 계정입니다. 따라서, 그에 맞게 regedit.exe를 이용해서 HKEY_CLASSES_ROOT에 권한을 추가해 주면 됩니다.

두 번째, ASP.NET 작업자 프로세스 계정을 "Administrators"에 가입된 계정이나, "SYSTEM" 계정으로 설정하는 것입니다. 이것 역시, IIS 버전에 따라 틀린데요. IIS 5.0에서는 .NET Framework이 설치되어져 있는 폴더의 Machine.config에서 processModel 요소를 수정해 주면 됩니다. 일례로, .NET 1.1의 경우에,

C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\CONFIG\machine.config

위의 파일을 열어서,

<processModel enable="true" ..... userName="SYSTEM" password="AutoGenerate" ... maxIoThreads="20" />

위와 같이 userName 속성에 적절한 계정을 넣어주시면 됩니다.

IIS 6.0의 경우에는 해당 웹 사이트 또는 가상 디렉토리가 Application Pool의 적용을 받기 때문에 해당 App Pool의 ID 탭에서 계정을 설정해 주시면 됩니다 다음과 같은 화면처럼.

Application Pool 계정 설정


첫 번째 방식과, 두 번째 방식의 장단점을 비교해 보면.

첫 번째의 레지스트리 키에 직접 보안이 낮은 계정을 추가하는 것은 오히려 보안 위험도를 높일 수가 있는 점이 있습니다. 물론, 두 번째의 설정은 오히려 더 보안 위험도가 높을 수 있는 것입니다. 레지스트리 하나 보호하려고 Front-End 단에서 (무작위) 사용자 코드 실행을 담당하는 Web Application의 권한을 높여주는 것이기 때문입니다. 즉, Web Application의 보안에 구멍이 뚫리기 시작하면, 레지스트리 하나 정도로 끝날 문제는 아니라는 거죠.

이런 문제로 인해, MS에서 제시하는 것은 Web Application을 구동하는 별도의 계정을 만들어서 적절한 권한만을 주는 것입니다. 하지만, 애플리케이션을 작성하다 보면, 도저히 일반 계정으로는 일일이 보안 설정을 다 못하는 경우가 있습니다. 일반 계정 하나 만들어 놓고, 그걸 가지고 필요한 보안 설정을 하다 보면, 결국 Administrator나 SYSTEM 계정과 권한이 비슷한 수위에 올라오게 되는 것인데요.

어쨌든, 선택은 여러분들 또는 그 위의 보안 담당자 및 운영자와 적절하게 상의를 하셔야 할 것이고요.

저에게 물으신다면... 아래와 같이 답하고 싶습니다.
만약, 위와 같이 COM+ 개체 하나 정도의 등록 때문이라면, 첫 번째 및 두 번째 방식을 모두 선택하지 않을 것입니다. 왜냐면, 결국 COM+ 등록은 레지스트리에 최초 한 번만 씌여지면 그만이므로, 한 번의 등록시에만 권한이 있는 사용자로 로그인해서 등록을 시키고, 이후에는 다시 "Network Service" 등의 계정으로 구동을 시킬 것입니다.
[연관 글]






[최초 등록일: ]
[최종 수정일: 6/24/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 151  152  153  154  155  156  [157]  158  159  160  161  162  163  164  165  ...
NoWriterDateCnt.TitleFile(s)
1119정성태9/11/201126611Java: 4. 이클립스에 WTP SDK가 설치되지 않는다면? [2]
1118정성태9/11/201138245Java: 3. 이클립스에서 서블릿 디버깅하는 방법 [4]
1117정성태9/9/201125539제니퍼 .NET: 17. 제니퍼 닷넷 적용 사례 (2) - 웹 애플리케이션 hang의 원인을 알려주다.
1116정성태9/8/201156624Java: 2. 자바에서 "Microsoft SQL Server JDBC Driver" 사용하는 방법
1115정성태9/4/201130093Java: 1. 닷넷 개발자가 처음 실습해 본 서블릿
1114정성태9/4/201134612Math: 2. "Zhang Suen 알고리즘(세선화, Thinning/Skeletonization)"의 C# 버전 [4]파일 다운로드1
1113정성태9/2/201134197개발 환경 구성: 129. Hyper-V에 CentOS 설치하기
1112정성태9/2/201150927Linux: 1. 리눅스 <-> 윈도우 원격 접속 프로그램 사용 [3]
1111정성태8/29/201125395제니퍼 .NET: 16. 적용 사례 (1) - DB Connection Pooling을 사용하지 않았을 때의 성능 저하를 알려주다. [1]
1110정성태8/26/201126726오류 유형: 136. RDP 접속이 불연속적으로 끊기는 문제
1109정성태8/26/201129576오류 유형: 135. 어느 순간 Active Directory 접속이 안되는 문제
1108정성태8/22/201131168오류 유형: 134. OLE/COM Object Viewer - DllRegisterServer in IVIEWERS.DLL failed. [1]
1107정성태8/21/201128872디버깅 기술: 43. Windows Form의 Load 이벤트에서 발생하는 예외가 Visual Studio에서 잡히지 않는 문제
1106정성태8/20/201127206웹: 26. FailedRequestTracing 설정으로 인한 iisexpress.exe 비정상 종료 문제
1105정성태8/19/201127126.NET Framework: 238. Web Site Model 프로젝트에서 Trace.WriteLine 출력이 dbgview.exe에서 확인이 안 되는 문제파일 다운로드1
1104정성태8/19/201127286웹: 25. WebDev보다 IIS Express가 더 나은 점 - 다중 가상 디렉터리 매핑 [1]
1103정성태8/19/201133172오류 유형: 133. WCF 포트 바인딩 실패 오류 - TCP error(10013) [1]
1102정성태8/19/201130947Math: 1. 방탈출3 - Room 10의 '중복가능한 조합' 문제를 위한 C# 프로그래밍 [2]파일 다운로드1
1101정성태8/19/201129618.NET Framework: 237. WCF AJAX 서비스와 JavaScript 간의 DateTime 연동 [1]파일 다운로드1
1100정성태8/17/201128725.NET Framework: 236. SqlDbType - DateTime, DateTime2, DateTimeOffset의 차이점파일 다운로드1
1099정성태8/15/201128151오류 유형: 132. 어느 순간 갑자기 접속이 안 되는 TFS 서버
1098정성태8/15/201150166웹: 24. 네이버는 어떻게 로그인 처리를 할까요? [2]
1097정성태8/15/201121465.NET Framework: 235. 메서드의 메타 데이터 토큰 값으로 클래스를 찾아내는 방법
1096정성태8/15/201125624디버깅 기술: 42. Watson Bucket 정보를 이용한 CLR 응용 프로그램 예외 분석 - (2)
1095정성태8/14/201126090디버깅 기술: 41. Windbg - 비정상 종료된 닷넷 프로그램의 StackTrace에서 보이는 offset 값 의미
1094정성태8/14/201130429오류 유형: 131. Fiddler가 강제 종료된 경우, 웹 사이트 방문이 안되는 현상
... 151  152  153  154  155  156  [157]  158  159  160  161  162  163  164  165  ...