SimpleIsBest.NET

유경상의 닷넷 블로그

ASP.NET에서 공유 폴더 액세스 (III)

by 블로그쥔장 | 작성일자: 2005-12-07 오전 11:57:00
이 글은 오래된 전에 작성된 글입니다. 따라서 최신 버전의 기술에 알맞지 않거나 오류를 유발할 수 있습니다. 저자는 이 글에 대한 질문을 받지 않을 것입니다. 하지만 이 글이 리뉴얼 되면 이 글에 대한 질문을 하거나 토론을 할 수도 있습니다.
ASP.NET에서 공유 폴더 액세스 시리즈의 세 번째 글입니다. 뭐 이렇게 굳이 씨리즈까정 운운하며 다룰 내용이 아닐 수도 있지만, 기왕 하는거 확실하게 뽕을 뽑아보려구 아조~~~ 자세하게 쓰고 있습니다. 너무 자세하게 쓰는 찝적이는 것이 오히려 독이 될 수 있다고 생각하지만...

그나저나 글이 너무 어렵다, 쉽다 혹은 이런 저런 이야기가 있으면 좋겠다 등등의 피드백은 전혀 없네요. 피드백이 없으니 제 맘대로 글을 쓸 수밖에 없는데... 제 글의 스타일이 어쩐지 당췌 알 수 없어서리... -_-;

지난 포스트에서는 프로그램이 공유 폴더에 액세스할 때 어떤 계정으로 파일 서버에 로그온 하는지 살펴보았습니다. 도메인으로 묶여 있지 않는 상황이라면 대개의 경우, 프로그램(프로세스)이 파일 서버에 로그온 하는 계정은 공유 폴더를 액세스하기에 적당하지 않습니다. 때문에 프로그램이 사용하는 계정을 바꾸어 주어야 하는데요... 이렇게 현재 쓰레드의 계정을 잠시 동안 바꾸는 방법에 대해 알아 보도록 하겠습니다.

참! 이 시리즈는 모두 5회로 계획되었으며(정말이야? 쓰다 보니 5회 분량이 나온 건 아니고? 알라고 하지마~~ 퍼버벅~) 다음 포스트는 대망의 ASP.NET에서 공유 폴더 액세스에 대한 부분이 되겠습니다. 마지막 5회에서는 네트워크 드라이브를 사용하는 방법에 대해 살펴볼 것이구요.

시리즈 목차

Accessing Shared Folder in ASP.NET (III)

지금까지 우리가 알아본 내용은 이렇다. 프로그램에서 파일 서버의 공유 폴더에 접근하기 위해서는, 일등으로 준비해야 할 것은 파일 서버에 적절한 계정(그룹을 사용하는 것이 더 좋다)으로 공유 폴더에 적절한 권한을 주고, 또 공유된 파일 시스템 폴더 역시 해당 계정에 적절한 권한을 주는 것이다. 적절한 계정 선택의 기준은 시리즈 첫 번째 글의 "Access Control" 부분을 참고하면 될 것이요,  공유 폴더에 구체적으로 권한을 주는 정책에 대해서는 시리즈 두 번째 글의 "Granting Access Right" 부분을 참고하면 될 것이다.

두 번째 해야 할 사항은 프로그램이 공유 폴더를 액세스할 수 있는 계정을 사용하도록 하는 것이다. 현재 프로그램이 사용하는 프로세스 계정 및 쓰레드 계정이 무엇인가를 알아내어, 공유 폴더에 액세스할 수 없다면 액세스할 수 있는 계정으로 바꾸어주는 작업이 필요하다. 프로세스 계정 그리고 쓰레드 계정을 바꾸는 방법은 다양하다. 일반적인 데스크톱 프로그램의 경우, Runas 커맨드나 "다음 계정으로 수행" 메뉴를 통할 수도 있지만 ASP.NET 작업 프로세스, COM+ 서버 프로세스, Windows 서비스 등은 다양한 설정을 필요로 한다(ASP.NET 에 대해서는 다음 포스트에서 알아보기로 하자. 쪼매만 참아라...).

Identify Thread Account

프로세스 계정보다 중요한 것은 현재 쓰레드가 사용하고 있는 쓰레드 계정이다. 지난 포스트의 테스트에서 살펴보았듯이 프로그램이 공유 폴더를 액세스할 때는 기본적으로 현재 쓰레드 계정을 이용하여 파일 서버에 로그온 하기 때문이다. 물론 나중에 살펴볼 네트워크 드라이브를 통해 파일 서버에 연결할 때는 아예 로그온 할 계정을 API 수준에서 명시할 수 있기 때문에 현재 쓰레드 계정이 별 의미가 없지만, 네트워크 드라이브를 사용하지 않을 때는 여전히 현재 쓰레드 계정이 무엇인가에 따라서 공유 폴더를 액세스하는데 성패가 좌우된다고 할 수 있다. 

먼저 알아볼 것은, 당췌 현재 쓰레드 계정이 무엇인가를 알아내는 방법에 대해 먼저 설명할까 한다. 지난 포스트에 언급했듯이 쓰레드의 계정은 디폴트로다가 프로세스 계정을 사용할 것이다. 프로세스 계정은 일반 데스크톱 프로그램은 현재 콘솔/터미널로 로그온된 사용자 계정을 따른다. 기타 Windows 서비스, ASP.NET 작업 프로세스는 해당 프로세스가 갖는 고유 설정을 따를 것이다. 이렇게 대략 추측은 가능하지만 확실히 눈으로 확인 하는 방법은 없을까?

System.Security.Principal 네임스페이스에는 WindowsIdentity 클래스가 존재한다. 이 클래스는 닷넷의 역할 기반 보안(role-based security)을 지원하기 위한 클래스로서 GenericIdentity 클래스와 더불어 현재 사용자를 나타낸다. GenericIdentity는 말 그대로 커스텀 인증을 사용할 때 사용하는 클래스이며, WindowsIdentity 클래스는 Windows 사용자 계정을 이용하여 역할 기반 보안을 구현하고자 할 때 사용되는 클래스이다. 용도가 어찌되었건 우리가 관심을 갖는 것은 WindowsIdentity 클래스의 스태틱 메쏘드인 GetCurrent() 메쏘드이다. 이 메쏘드는 현재 쓰레드의 쓰레드 계정(보다 정확히 말하자면 쓰레드 토큰이라고 봐야 한다. 토큰은 조금 있다 설명하겠다.)을 나타내는 WindowsIdentity 객체를 반환해 준다. 즉, WindowsIdentity.GetCurrent() 메쏘드를 호출하면 쓰레드 계정을 알아낼 수 있다는 것이 되겠다.

WindowsIdentity identity = WindowsIdentity.GetCurrent();

Console.WriteLine("Current Thread Account = {0}", identity.Name);

리스트1. 쓰레드 계정을 알아내는 코드

예제라고 하기에도 뭐한 이 코드 조각(리스트1)이 현재 쓰레드 계정을 표시하는 코드가 되겠다. 너무 짧아서 쪽팔릴 정도이다. 어찌되었건 WindowsIdentity 클래스의 GetCurrent() 메쏘드는 쓰레드 계정이 어떤 것인지 알아내는 방법이란 것만 알아 두자.

Changing Thread Account

현재 쓰레드의 쓰레드 계정이 무엇인지 알아낼 수 있으므로 바꿀 수도 있을 것이다. 이렇게 쓰레드의 계정을 바꾸는 것을 가장(impersonation)이라고 한다. 먼저 가장에 대한 일반적인 내용을 살펴보고 구체적으로 가장을 수행하기 위한 닷넷 코드를 살펴보자.

Impersonation

) 이 내용은 닷넷과 IIS Security에서 Impersonation 토픽 부분을 약간 각색하여 옮긴 것이다. (참고하라고만 하면 잘 안보기 때문에...)

가장(impersonation)이란 용어는 Visual Studio .NET에 포함된 한글판 MSDN 라이브러리에서 사용되는 용어이다. 다른 책들에서는 '인격화' 혹은 '흉내내기' 라는 용어가 사용되기도 한다. 대략 뷁스런 용어로서 한글화하기가 아주 지랄 맞은 단어이다. 개인적인 의견으로는 어정쩡하고 직관적이지 않는 가장 이나 인격화 같은 용어보다는 직관적인 흉내내기 라는 용어가 마음에 들지만 MSDN을 자주 참고할 독자들을 위해 ‘가장’ 이라는 용어를 사용하겠다. (참고로 필자는 한글 MSDN을 보지 않는다)

가장(Impersonation)은 말 그대로 계정을 흉내낸다는 말이다. 대개의 데스크톱 어플리케이션(오피스, 노트패드 등등)은 가장을 필요로하지 않는다. 가장이 필요한 어플리케이션은 대개 서버측 어플리케이션으로서 클라이언트가 서버에 대해 권한이 있는가를 검사하는데 사용되어 진다. 즉, 서버가 클라이언트로부터 파일 액세스와 같은 서비스 요청을 받았을 때 클라이언트가 이러한 서비스에 대한 권한을 갖고 있는가를 검사할 때 사용된다는 말이다.

그런데 이러한 권한 검사에서 왜 가장을 사용할까? 이 질문에 대해 필자는 “가장을 사용하지 않는 경우에는 어떻게 권한 검사를 하는가?” 라고 반문을 하고 싶다. 가장을 사용하지 않는다면 서버는 클라이언트의 액세스 토큰이 액세스 하고자 하는 서버 자원(이 경우 파일)에 대한 권한이 있는가를 검사해야 할 것이다. 이러한 권한 검사를 위해 서버는 파일과 같은 서버 자원의 ACL(Access Control List; 읽기/쓰기 등 사용 권한을 기록해 놓은 정보라고 생각하면 된다)를 읽어야 하고 클라이언트의 액세스 토큰(사용자 계정으로 생각하자)과 ACL를 비교 검사하여 권한이 있고 없음을 결정해야 할 것이다. 하지만 이러한 작업은 이미 Windows 커널 내에서 수행하는 작업 아닌가? Windows 커널은 컴퓨터의 자원을 액세스할 때 이러한 보안 검사를 수행하도록 되어 있다. 다만 주의할 점은 서버 자원의 ACL과 서버 프로그램의 권한을 비교하는 것이 아니라 서버 자원의 ACL과 클라이언트 계정의 권한을 비교해야 한다는 점에서 다르다. 이때 서버 프로그램이 클라이언트 계정인 것 처럼 흉내를 내면 어떨까? 서버 프로그램이 자신을 클라이언트 계정인 것처럼 흉내 낸 다음 파일을 액세스 한다면 Windows 커널은 클라이언트 계정의 권한과 파일에 주어진 ACL을 비교하여 보안 검사를 수행하게 될 것이다. 이처럼 가장은 서버측에서 클라이언트들의 권한 검사를 보다 손쉽게 해주는 방법으로 생각하면 될 것이다.

FTP를 예로 들어 보자. FTP에 접속한 사용자는 자신의 계정과 암호를 밝힐 것이다. FTP 서버는 이 계정과 암호를 이용해 가장을 수행한다. 그리고 FTP 클라이언트가 다운로드할 파일을 읽으려고 시도한다. 만약 사용자가 제시한 계정이 해당 파일에 대한 읽기 권한이 없다면 오류가 발생할 것이고 FTP 서버는 이 오류 내용을 클라이언트에게 넘겨주면 된다!

가장을 수행하기 위해서는 SetThreadToken API를 호출해야 한다. 이 API는 매개변수로서 액세스 토큰(Access Token)을 취하는데, 액세스 토큰을 얻기 위한 방법은 여러 가지 API 중에 LogonUser 함수를 호출하는 것이다. 이 API 함수는 사용자 계정, 암호, 도메인 등을 매개변수로 취하기 때문에 사용하기 편리하다. LogonUser 함수에 대한 상세한 내용은 MSDN을 참고하기 바란다. LogonUser 함수를 호출하면 액세스 토큰이 만들어지고 이 액세스 토큰에 대한 핸들을 반환한다. 이 핸들을 SetThreadToken 함수의 매개변수로 사용하면 가장이 수행되는 것이다.

액세스 토큰 혹은 그냥 줄여서 토큰이라 함은 프로세스 혹은 쓰레드의 보안 문맥(security context)을 기술하는 Windows의 커널 객체를 말한다. 사용자(사람)이 컴퓨터에 로그온 할 때는 계정(account)을 사용하게 된다. 그리고 이 사용자가 어떤 프로그램을 수행시키면 이 프로그램은 그 사용자의 계정으로 작동하게 된다. 즉, joe라는 계정을 사용하는 사용자가 notepad.exe를 수행시켰다면 이 notepad.exe는 joe라는 계정 하에서 작동한다는 말이다(입이 아프도록 반복 했다. -_-). 이는 joe라는 계정이 갖는 각종 권한을 notepad.exe도 갖는다는 말과 같은 말이다. 이 때 notepad.exe 프로세스가 어떤 계정 하에서 수행 중이며 어떤 특권을 갖고 있는지, 그리고 특별한 권한 명세가 없을 때 사용되는 디폴트 액세스 권한은 어떤 것인지에 대한 정보를 가지고 있는 것이 액세스 토큰인 것이다.

가장 토큰을 갖는 쓰레드는 언제든지 RevertToSelf 라는 함수를 호출하여 가장을 중지할 수 있다. 가장이 중지되면 쓰레드는 즉시 프로세스 계정, 소위 프라이머리 토큰(primary token)으로 즉시 환원된다.

Impersonation in .NET

닷넷 개발환경은 가장(impersonation)에 대한 지원을 얼마나 할까? 그게 좀 아리까리 하다. 잘 지원한다고 말하기도 어렵고 전혀 지원하지 않는다고 말하기도 어렵기 때문이다.

앞서 언급한 WindowsIdentity 클래스는 가장을 위해 Impersonate() 메쏘드를 가지고 있다. 그런데 이 녀석은 액세스 토큰을 항상 요구한다. 그렇다면 LogonUser API 함수와 같이 닷넷에도 액세스 토큰을 얻을 수 있는 메쏘드가 있을까? 아쉽게도 (적어도 필자가 아는 한) 이런 메쏘드가 없다. 이거 장난 치는 것도 아니고, 버젓이 Impersonate() 메쏘드를 제공하면서도 액세스 토큰을 얻어낼 방법을 제공하지 않는 심보는 또 뭔지 대략 짜증나지만... 어쩔 수 있는가? P/Invoke를 또 써야만 한다. 즉 P/Invoke를 이용하여 LogonUser 를 호출하고 그 결과로 액세스 토큰을 얻어낸 다음에 이 액세스 토큰을 이용하여 Impersonate 메쏘드를 호출하면 가장을 수행할 수 있다.

먼저 LogonUser API 에 대한 P/Invoke 선언을 살펴보자. 필자가 미덥지 않다면 PINVOKE.NET 에서 검색해 봐도 무방하다. 리스트2는 필자가 작성한 LogonUser API 에 대한 P/Invoke 선언 및 그에 대한 wrapper 메쏘드이다.

    1 /// <summary>

    2 /// LogonUser API에서 사용하는 로그온 타입

    3 /// </summary>

    4 public enum LogonType

    5 {

    6     LOGON32_LOGON_INTERACTIVE = 2,

    7     LOGON32_LOGON_NETWORK = 3,

    8     LOGON32_LOGON_BATCH = 4,

    9     LOGON32_LOGON_SERVICE = 5,

   10     LOGON32_LOGON_UNLOCK = 7,

   11     LOGON32_LOGON_NETWORK_CLEARTEXT = 8,

   12     LOGON32_LOGON_NEW_CREDENTIALS = 9

   13 }

   14 

   15 /// <summary>

   16 /// LogonUser API에서 사용하는 로그온 프로바이더

   17 /// </summary>

   18 public enum LogonProvider

   19 {

   20     LOGON32_PROVIDER_DEFAULT = 0,

   21     LOGON32_PROVIDER_WINNT35 = 1,

   22     LOGON32_PROVIDER_WINNT40 = 2,

   23     LOGON32_PROVIDER_WINNT50 = 3

   24 }

   25 

   26 /// <summary>

   27 /// WIN32 Security 관련 API 들에 대한 모음

   28 /// </summary>

   29 public class SecurityAPI

   30 {

   31     const int ERROR_INSUFFICIENT_BUFFER = 122;

   32 

   33     [DllImport("advapi32.dll", EntryPoint="LogonUser", SetLastError=true)]

   34     private static extern bool _LogonUser(string lpszUsername, string lpszDomain, string lpszPassword,

   35             int dwLogonType, int dwLogonProvider, out int phToken);

   36 

   37     /// <summary>

   38     /// 주어진 사용자 ID로 로그온하여 액세스 토큰을 반환한다.

   39     /// </summary>

   40     /// <param name="userName">사용자 ID</param>

   41     /// <param name="password">암호</param>

   42     /// <param name="domainName">도메인 이름</param>

   43     /// <param name="logonType">로그온 종류</param>

   44     /// <param name="logonProvider">로그온 프로바이더</param>

   45     /// <returns></returns>

   46     public static IntPtr LogonUser(string userName, string password, string domainName,

   47         LogonType logonType, LogonProvider logonProvider)

   48     {

   49         int token = 0;

   50         bool logonSuccess = _LogonUser(userName, domainName, password,

   51                 (int)logonType, (int)logonProvider, out token);

   52         if (logonSuccess)

   53             return new IntPtr(token);

   54         int retval = Marshal.GetLastWin32Error();

   55         throw new Win32Exception(retval);

   56     }

   57 }

리스트2. LogonUser API에 대한 선언 및 Wrapper 메쏘드

실제 P/Invoke 선언은 33-35 라인이지만 이 선언을 직접 사용하지 않고 wrapper 메쏘드를 만들었다(46-56 라인). 이렇게 함으로써 예외 처리나 기타 매개변수 변환 등의 작업을 수행할 수 있어 호출자가 편리하게 사용할 수 있다. 이 외에 LogonType 열거자, LogonProvider 열거자는 LogonUser 함수에 대한 MSDN 도움말을 살펴보기 바란다. 간략하게 설명하자면 LogonType 은 LogonUser 함수가 생성할 액세스 토큰이 인터액티브 로그온(콘솔/터미널 로그온)인지 네트워크 액세스를 위한 로그온인지 등을 결정할 때 사용한다. LogonProvider는 어떤 로그온 제공자를 사용할 것인가를 명시하는데 항상 DEFALUT를 사용한다고 생각하면 된다.

이제 리스트2의 코드를 사용하는 예제 코드(리스트3)를 살펴보자. 먼저 가장(impersonation) 전에 쓰레드 계정을 표시하고(1-3 라인), 가장을 수행한다(5-13 라인). 그리고 나서 쓰레드 계정을 표시하여 가장이 수행되었는가를 확인한다(15-17 라인). 이제 가장이 성공하였으므로, 공유 폴더를 액세스하던, 파일 액세스를 하건 필요한 작업을 수행한다(19-20 라인. 생략됨). 필요한 액세스를 완료했으면 가장을 취소(revoke) 해야 한다(22-23라인). Impersonate 메쏘드를 호출한 결과로 반환한 WindowsImpersonationContext 객체의 Undo 메쏘드를 호출하면 가장이 취소되어 프라이머리 토큰(primary token; 프로세스 계정이다)으로 되돌아가게 된다. 확실히 가장이 취소 되었는가를 최종적으로 확인하는 코드도 포함되어 있다(라인 25-27).

    1 // 현재 쓰레드 계정 정보 표시

    2 WindowsIdentity identity = WindowsIdentity.GetCurrent();

    3 Console.WriteLine("Before Impersonation :: Current Thread Account = {0}", identity.Name);

    4 

    5 // Impersonation 수행

    6 IntPtr token = SecurityAPI.LogonUser("TestUser", "1234", ".",

    7                         LogonType.LOGON32_LOGON_NETWORK_CLEARTEXT,

    8                         LogonProvider.LOGON32_PROVIDER_DEFAULT);

    9 WindowsImpersonationContext ctx = WindowsIdentity.Impersonate(token);

   10 // 혹은 다음과 같이 WindowsIdentity 객체를 만들어서 Impersonate 메쏘드를 호출해도

   11 // 된다.

   12 // identity = new WindowsIdentity(token);

   13 // WindowsImpersonationContext ctx = identity.Impersonate();

   14 

   15 // Impersonation 수행 후의 쓰레드 계정 표시

   16 identity = WindowsIdentity.GetCurrent();

   17 Console.WriteLine("After Impersonation :: Current Thread Account = {0}", identity.Name);

   18 

   19 // 여기에서 파일 액세스, 네트워크 액세스나 기타 자원을 액세스 한다.

   20 // 이들 자원에 대한 액세스는 impersonate 된 계정을 사용하여 액세스하게 될 것이다.

   21 

   22 // 수행한 impersonation을 revoke 한다.

   23 ctx.Undo();

   24 

   25 // revoke 후에 쓰레드 계정 표시

   26 identity = WindowsIdentity.GetCurrent();

   27 Console.WriteLine("After Revoke :: Current Thread Account = {0}", identity.Name);

리스트3. Impersonation 수행 예제 코드

Test

지난 포스트에서 수행했던 테스트를 잘 기억해 보자. 아주 간단한 코드를 통해 공유 폴더를 액세스 했고 이 액세스는 실패 했었다. 대신 프로세스 계정을 runas 커맨드와 같은 방법으로 바꾸었을 때는 성공했었다. 그렇다면 가장(impersonation)을 이용하여 현재 쓰레드의 계정을 바꾸면 공유 폴더 액세스를 성공할까? 물론 가장에 사용할 계정은 TestUser 계정이어야 할 것이다. 리스트2의 코드를 지난 포스트의 테스트 코드에 추가하고 Main 메쏘드에 가장을 수행하는 코드를 수정하여 다음 리스트4 처럼 바꾸어 보자.

    1 public static void Main()

    2 {

    3     // Impersonation 수행

    4     IntPtr token = SecurityAPI.LogonUser("TestUser", "1234", ".",

    5         LogonType.LOGON32_LOGON_NETWORK_CLEARTEXT,

    6         LogonProvider.LOGON32_PROVIDER_DEFAULT);

    7     WindowsIdentity identity = new WindowsIdentity(token);

    8     WindowsImpersonationContext ctx = identity.Impersonate();

    9 

   10     // 공유 폴더 액세스

   11     FileStream stream = new FileStream(@"\\192.168.2.4\Share\data.dat", FileMode.Open);

   12     stream.Close();

   13 

   14     // 수행한 impersonation을 revoke 한다.

   15     ctx.Undo();

   16 }

리스트4. Impersonation을 수행한 이후에 공유 폴더 액세스

쓰레드 계정을 코드에 의해 바꾸었으므로, 지난 포스트의 테스트 처럼 runas.exe 커맨드를 사용하지 않아도 위 코드는 정상적으로 공유 폴더를 액세스할 것이다 !

Summary

프로그램에서 파일 경로에 UNC (Universal Name Convention) 경로를 명시하여 공유 폴더를 액세스하면, 현재 쓰레드의 계정을 이용하여 파일 서버에 로그온 하게 된다. 대개의 경우, 이 쓰레드 계정은 파일 서버에 로그온 할 수 없거나, 로그온이 가능하더라도 권한이 없는 경우가 많으므로 적절한 계정으로 쓰레드 계정을 바꾸어 줄 필요가 있다.

현재 쓰레드의 계정을 바꾸기 위해서는 가장(impersonation)을 수행해야 하며, 가장을 수행하기 위해서는 가장 하고자 하는 계정의 액세스 토큰을 구해야 한다. 아쉽게도 닷넷은 액세스 토큰을 구하는 메쏘드를 제공하지 않으므로 P/Invoke를 통해 액세스 토큰을 구하고 이 액세스 토큰으로 부터 WindowsIdentity.Impersonate() 메쏘드를 호출하여 가장을 수행한다. 이렇게 가장을 수행하면 현재 쓰레드의 계정이 가장된 계정으로 바뀌게 되므로, 이 이후에 공유 폴더를 액세스하면 로그온과 더불어 공유 폴더를 성공적으로 액세스할 수 있다.

ASP.NET의 상황에서도 동일한 방법을 사용하면 공유 폴더를 액세스할 수 있다. 그러나 ASP.NET이 무엇이던가? 이러한 가장을 수행하는 코드를 작성하지 않더라도 web.config 의 설정으로도 동일한 효과를 거둘 수 있다. 쓰바 이 말이 하고 싶어서 지금까지 필자는 그렇게 삽질해 왔던 것이다. ASP.NET에서 공유 폴더 액세스. 이거 조또 아니다. Impersonation을 수행하면 거의 무조건 된다. 아니면 약간의 단점이 있지만 web.config에 적절한 설정을 해주던가... 기본 사항들만 알고 있으면 조또 아닌 것을 설명하기 위해 입에 침을 튀어가면서 이렇게 씨리즈로다가 글을 써 온 것이다.

다음 포스트에서는 가장 관련 코드를 사용하지 않을 경우에 해야 할 ASP.NET의 web.config 설정 무엇이며 장/단점은 또 무엇인가를 알아보도록 하겠다. 개봉 박두~~~ -_-;



Comments (read-only)
#re: ASP.NET에서 공유 폴더 액세스 (III) / webgenie / 2005-12-08 오후 12:14:00
좋은 글 잘읽고 갑니다.
전 요즘 통 글을 못 쓰는데 어찌 이리 꼬박꼬박 쓰시는지.. 반성하고 갑니다.. ㅠㅠ
#re: ASP.NET에서 공유 폴더 액세스 (III) / 김형태 / 2006-04-04 오후 3:06:00
재미있게 글 읽고 갑니다
#re: ASP.NET에서 공유 폴더 액세스 (III) / 김지남 / 2006-05-15 오전 10:47:00
질문있습니다.
IntPtr token = SecurityAPI.LogonUser("TestUser", "1234", ".", LogonType.LOGON32_LOGON_NETWORK_CLEARTEXT,LogonProvider.LOGON32_PROVIDER_DEFAULT);
여기서 세번째 파라미터에는 "."라도 되어 있는데요 컴퓨터 이름을 쓰는건가요? 아니면 아이피?
계속 알수없는 사용자 이름이거나 암호가 틀립니다. 라는 에러가 발생합니다.
ㅠㅠ
가르쳐 주세요..

#re: ASP.NET에서 공유 폴더 액세스 (III) / 블로그쥔장 / 2006-05-15 오전 11:03:00
세번째 매개변수는 Windows 도메인 입니다.
인터넷 DNS 도메인이 아닙니다. Acitve Directory로 도메인이 구성되어 있다면
이 도메인의 이름을 넣으면 됩니다. 도메인이 없다면 예제 코드 처럼 "." 을 넣으시면 됩니다.
. 을 넣었는데도 사용자 이름이나 암호가 틀리다는 메시지가 나온다면 파일 서버에서 해당 계정이름과
암호를 확인하시기 바랍니다.
#re: ASP.NET에서 공유 폴더 액세스 (III) / 이준호 / 2006-06-15 오후 4:38:00
글이 너무 어렵습니다. 제가 잘 몰라서요^^;;
애니웨이 이런글 시간내서 올려주시니 너무 감사하네요
#re: ASP.NET에서 공유 폴더 액세스 (III) / chad kim / 2007-12-21 오후 3:35:00
정말 자세한 설명에 감탄했습니다.
작성하시느라 고생이 많으신 만큼 저와 같이 잘 모르는 사람에게 큰 도움을 주신것 같네요..

감사합니다.
#re: ASP.NET에서 공유 폴더 액세스 (III) / kral oyun / 2007-12-30 오전 6:59:00
Thanks