프로젝트 진행중에 네트워크 드라이브에 엑셀파일을 업로드를 하고 그 파일을 열어서 Formula 를 읽어서 수식 계산 후에 클라이언트로 내려 주는 기능이 필요 하게 되었습니다.
먼저 네트워크 드라이브는 연결을 하게 되면 기본적으로 아이디 패스워드만 맞춰 주면 업로드 다운로드는 가능 하더군요..
그러나 파일을 오픈 하게 되면 엑세스 오류를 던집니다.
이런 경우 웹계정을 윈도우즈 계정으로 가장 하여 실행을 할 수 있습니다.
쉽게 말해 서버 운영체제에 있는 계정으로 로그인을 하여 그 권한을 획득 하는 것이죠..
기본적인 사항은 MSDN문서를 참고 하시면 되겠습니다.
위 문서중에 모든 연결에 대하여 가장을 하는 경우
즉 web.config에서
이거 아마도 추측 하기에 웹계정이 윈도우계정으로 가장되어서 윈도우계정이 웹권한이 없기 때문이 아닐까....생각해 봅니다..ㅡ.ㅡ;;
가장을 사용하기 위해서는...
서버에 계정과 비밀번호를 할당 합니다.
이 계정에는 기본적으로 제일 적은 권한인 Guests Role을 주고 나머지 Role은 제거 하는게 좋을 듯 싶습니다.
네트워크 서버에는 이 계정과 비밀번호가 같은 계정을 생성하여 공유하고자 하는 폴더를 공유 합니다.
이 절차가 끝나면 서버에서 윈도우즈 탐색기를 통해 위 계정으로 네트워크 서버에 접속이 가능하여야 합니다.
어쨋든..저는 코드에서 구현 하는 것으로 사용 하였습니다.
public const int LOGON32_LOGON_INTERACTIVE = 2; public const int LOGON32_PROVIDER_DEFAULT = 0; WindowsImpersonationContext impersonationContext; [DllImport("advapi32.dll")] public static extern int LogonUserA(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken); [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern bool RevertToSelf(); [DllImport("kernel32.dll", CharSet=CharSet.Auto)] public static extern bool CloseHandle(IntPtr handle); public void Page_Load(Object s, EventArgs e) { if(impersonateValidUser("username", "domain", "password")) { //Insert your code that runs under the security context of a specific user here. undoImpersonation(); } else { //Your impersonation failed. Therefore, include a fail-safe mechanism here. } } private bool impersonateValidUser(String userName, String domain, String password) { WindowsIdentity tempWindowsIdentity; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero; if(RevertToSelf()) { if(LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0) { if(DuplicateToken(token, 2, ref tokenDuplicate) != 0) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); impersonationContext = tempWindowsIdentity.Impersonate(); if (impersonationContext != null) { CloseHandle(token); CloseHandle(tokenDuplicate); return true; } } } } if(token!= IntPtr.Zero) CloseHandle(token); if(tokenDuplicate!=IntPtr.Zero) CloseHandle(tokenDuplicate); return false; } private void undoImpersonation() { impersonationContext.Undo(); }
참고로 AD가 구현 되어 있지 않았다면 domain은 빈값을 넣어 주면 되겠습니다.
그러나..서버에 배포시 문제가 생겼습니다.
로컬 및 테스트 서버에서는 잘 작동 하였는데..서버에 배포를 하니..로그인 실패가 뜨는 것입니다.
LogonUserA 메서드가 false를 던지는 것이죠.
일반적으로 운영 서버의 경우 보안의 제약 사항이 많기 때문에 많은 제약 사항 중에 해당 되는 것을 찾아야 했습니다.
음.
결론은 로컬보안정책 > 사용자 권한 할당 > 로컬 로그온 허용 에 해당 계정을 넣어주면 되었습니다.
완전..개고생 했네요..
PS . 네트워크 서버의 경로는 코드 상에 UNC 경로로 입력 하여야 합니다.