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

비밀번호

댓글 작성자
 




1  2  3  4  [5]  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13530정성태1/15/20242344닷넷: 2203. C# - Python과의 AES 암호화 연동파일 다운로드1
13529정성태1/15/20242346닷넷: 2202. C# - PublishAot의 glibc에 대한 정적 링킹하는 방법
13528정성태1/14/20242490Linux: 68. busybox 컨테이너에서 실행 가능한 C++, Go 프로그램 빌드
13527정성태1/14/20242349오류 유형: 892. Visual Studio - Failed to launch debug adapter. Additional information may be available in the output window.
13526정성태1/14/20242440닷넷: 2201. C# - Facebook 연동 / 사용자 탈퇴 처리 방법
13525정성태1/13/20242346오류 유형: 891. Visual Studio - Web Application을 실행하지 못하는 IISExpress
13524정성태1/12/20242400오류 유형: 890. 한국투자증권 KIS Developers OpenAPI - GW라우팅 중 오류가 발생했습니다.
13523정성태1/12/20242202오류 유형: 889. Visual Studio - error : A project with that name is already opened in the solution.
13522정성태1/11/20242410닷넷: 2200. C# - HttpClient.PostAsJsonAsync 호출 시 "Transfer-Encoding: chunked" 대신 "Content-Length" 헤더 처리
13521정성태1/11/20242518닷넷: 2199. C# - 한국투자증권 KIS Developers OpenAPI의 WebSocket Ping, Pong 처리
13520정성태1/10/20242289오류 유형: 888. C# - Unable to resolve service for type 'Microsoft.Extensions.ObjectPool.ObjectPool`....'
13519정성태1/10/20242257닷넷: 2198. C# - Reflection을 이용한 ClientWebSocket의 Ping 호출파일 다운로드1
13518정성태1/9/20242504닷넷: 2197. C# - ClientWebSocket의 Ping, Pong 처리
13517정성태1/8/20242330스크립트: 63. Python - 공개 패키지를 이용한 위성 이미지 생성 (pystac_client, odc.stac)
13516정성태1/7/20242420닷넷: 2196. IIS - AppPool의 "Disable Overlapped Recycle" 옵션의 부작용
13515정성태1/6/20242779닷넷: 2195. async 메서드 내에서 C# 7의 discard 구문 활용 사례 [1]
13514정성태1/5/20242438개발 환경 구성: 702. IIS - AppPool의 "Disable Overlapped Recycle" 옵션
13513정성태1/5/20242378닷넷: 2194. C# - WebActivatorEx / System.Web의 PreApplicationStartMethod 특성
13512정성태1/4/20242336개발 환경 구성: 701. IIS - w3wp.exe 프로세스의 ASP.NET 런타임을 항상 Warmup 모드로 유지하는 preload Enabled 설정
13511정성태1/4/20242327닷넷: 2193. C# - ASP.NET Web Application + OpenAPI(Swashbuckle) 스펙 제공
13510정성태1/3/20242227닷넷: 2192. C# - 특정 실행 파일이 있는지 확인하는 방법 (Linux)
13509정성태1/3/20242362오류 유형: 887. .NET Core 2 이하의 프로젝트에서 System.Runtime.CompilerServices.Unsafe doesn't support netcoreapp2.0.
13508정성태1/3/20242404오류 유형: 886. ORA-28000: the account is locked
13507정성태1/2/20243148닷넷: 2191. C# - IPGlobalProperties를 이용해 netstat처럼 사용 중인 Socket 목록 구하는 방법파일 다운로드1
13506정성태12/29/20232658닷넷: 2190. C# - 닷넷 코어/5+에서 달라지는 System.Text.Encoding 지원
13505정성태12/27/20233262닷넷: 2189. C# - WebSocket 클라이언트를 닷넷으로 구현하는 예제 (System.Net.WebSockets)파일 다운로드1
1  2  3  4  [5]  6  7  8  9  10  11  12  13  14  15  ...