Имитация с Win32 API за достъп до мрежов дял срещу четене на мрежов дял с Windows Explorer?

Имам уеб приложение, което се представя с помощта на Win32 API. Наскоро се върнах от пътуване, за да открия, че частта от приложението, която се представя, се проваля.

Причината за представянето е, че има мрежов дял, който се използва за конкретна цел. Когато моето уеб приложение получи достъп до този мрежов дял, то трябва да се представя за специален акаунт. За целите на дискусията uid е "Bob", паролата е "1234", а домейнът е "home".

Преди две седмици написах моята програма за използване на Win32 API, за да се представя за Боб и всичко беше наред. Сега API на Win32 показва грешка при влизане. Имам проблем да разбера какво може да се е променило. За да бъдем конкретни, сървърът показва, че не успява да имитира Боб. Грешката възниква преди сървърът действително да се опита да получи достъп до мрежов дял.

Странното е, че ако се свържа с моя уеб сървър с MSTSC, мога да щракна върху „Map Network Drive“ в Windows Explorer и да получа достъп до файловете, използвайки Bob@home и парола 1234. (Въвеждам uid и парола като щракнете върху „Свързване с друго потребителско име“ в диалоговия прозорец „Картиране на мрежово устройство“)

Изглежда, че трябва да се случва нещо различно, когато се опитвам да осъществя достъп до моя мрежов дял с имитация, отколкото с помощта на Windows Explorer.

Каква е тази разлика?

Актуализация: Чувствам, че отговорът на този проблем е, че има някакво разрешение за влизане, което се отказва, което по някакъв начин не е включено, когато влизам в моите файлове през Windows Explorer.


person Vivian River    schedule 17.10.2011    source източник
comment
Питате ли каква е разликата между достъпа до споделянето чрез имитация и достъпа до него чрез Windows Explorer от вашия акаунт на вашата машина? Можете ли да публикувате някакъв код?   -  person James Johnson    schedule 17.10.2011
comment
Питам каква е разликата между достъпа до споделянето чрез имитация и достъпа до него през Windows Explorer със същия акаунт, използван за имитация   -  person Vivian River    schedule 17.10.2011
comment
Проверихте ли разрешенията за споделянето? Предполагам, че сте посочили разрешения за папката, но много хора забравят да приложат разрешенията към споделянето.   -  person James Johnson    schedule 17.10.2011
comment
Да, разрешенията са проверени. Имам достъп до папката от всяко място в мрежата; Просто не мога да получа достъп до него чрез имитация.   -  person Vivian River    schedule 17.10.2011
comment
Посочвате ли домейна във вашия код за повикване?   -  person Josh    schedule 17.10.2011
comment
Как се опитвате да получите достъп до споделената папка? Използвате UNC пътя, нали?   -  person James Johnson    schedule 17.10.2011
comment
Да, използвам UNC пътя и посочвам домейна   -  person Vivian River    schedule 17.10.2011
comment
msdn.microsoft.com /en-us/library/ Уверете се, че имате ниво на делегат.   -  person thangcao    schedule 08.07.2014


Отговори (1)


Уверете се, че използвате UNC пътя за достъп до папката:

string path = @"\\server\folder";

Не знам как изглежда вашият клас за имитация, но ето клас, който използвам за подобни задачи:

/// <summary> 
/// Leverages the Windows API (advapi32.dll) to programmatically impersonate a user. 
/// </summary> 
public class ImpersonationContext : IDisposable 
{ 
    #region constants 

    private const int LOGON32_LOGON_INTERACTIVE = 2; 
    private const int LOGON32_PROVIDER_DEFAULT = 0; 

    #endregion 

    #region global variables 

    private WindowsImpersonationContext impersonationContext; 
    private bool impersonating; 

    #endregion 

    #region unmanaged code 

    [DllImport("advapi32.dll")] 
    private 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)] 
    private static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken); 

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern bool RevertToSelf(); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 
    private static extern bool CloseHandle(IntPtr handle); 

    #endregion 

    #region constructors 

    public ImpersonationContext() 
    { 
        impersonating = false; 
    } 

    /// <summary> 
    /// Overloaded constructor and begins impersonating. 
    /// </summary> 
    public ImpersonationContext(string userName, string password, string domain) 
    { 
        this.BeginImpersonationContext(userName, password, domain); 
    } 

    #endregion 

    #region impersonation methods 

    /// <summary> 
    /// Begins the impersonation context for the specified user. 
    /// </summary> 
    /// <remarks>Don't call this method if you used the overloaded constructor.</remarks> 
    public void BeginImpersonationContext(string userName, string password, string domain) 
    { 
        //initialize token and duplicate variables 
        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) 
                { 
                    using (WindowsIdentity tempWindowsIdentity = new WindowsIdentity(tokenDuplicate)) 
                    { 
                        //begin the impersonation context and mark impersonating true 
                        impersonationContext = tempWindowsIdentity.Impersonate(); 
                        impersonating = true; 
                    } 
                } 
            } 
        } 

        //close the handle to the account token 
        if (token != IntPtr.Zero) 
            CloseHandle(token); 

        //close the handle to the duplicated account token 
        if (tokenDuplicate != IntPtr.Zero) 
            CloseHandle(tokenDuplicate); 
    } 

    /// <summary> 
    /// Ends the current impersonation context. 
    /// </summary> 
    public void EndImpersonationContext() 
    { 
        //if the context exists undo it and dispose of the object 
        if (impersonationContext != null) 
        { 
            //end the impersonation context and dispose of the object 
            impersonationContext.Undo(); 
            impersonationContext.Dispose(); 
        } 

        //mark the impersonation flag false 
        impersonating = false; 
    } 

    #endregion 

    #region properties 

    /// <summary> 
    /// Gets a value indicating whether the impersonation is currently active. 
    /// </summary> 
    public bool Impersonating 
    { 
        get 
        { 
            return impersonating; 
        } 
    } 

    #endregion 

    #region IDisposable implementation 

    ~ImpersonationContext() 
    { 
        Dispose(false); 
    } 

    public void Dispose() 
    { 
        Dispose(true);                
    } 

    protected virtual void Dispose(bool disposing) 
    { 
        if (disposing) 
        { 
            if (impersonationContext != null) 
            { 
                impersonationContext.Undo(); 
                impersonationContext.Dispose(); 
            } 
        } 
    } 

    #endregion     
} 

Използване на ImpersonationContext:

using (ImpersonationContext context = new ImpersonationContext("user", "password", "domain")) 
{ 
    if (context.Impersonating) 
    { 
        Process.Start(@"/Support/SendFax/SendFax.exe"); 
    } 
} 
person James Johnson    schedule 17.10.2011
comment
Моят код е много подобен на вашия. Проблемът е, че кодът ми работеше, но вече не работи. - person Vivian River; 17.10.2011
comment
@RiceFlourCookies: Това изглежда показва промяна в разрешенията някъде. Опитвали ли сте временно да дадете неограничен достъп до папката, т.е. да дадете на всички пълни разрешения? - person James Johnson; 17.10.2011
comment
Когато стартирам кода си през дебъгера, той се проваля, когато се опитва да започне имитация. По-конкретно, изключение се хвърля преди сървърът дори да се опита да получи достъп до мрежовия дял. - person Vivian River; 17.10.2011
comment
Хм... и сигурен ли си, че потребителският акаунт е активен? Вашият код извиква ли RevertToSelf(), преди да се представи за потребителя? - person James Johnson; 17.10.2011
comment
Да, извиква RevertToSelf(). Също така открих, че кодът изглежда работи, когато се изпълнява в Casini на моята локална работна станция. Той обаче се проваля както на моите уеб сървъри за разработка, така и на производствени. - person Vivian River; 17.10.2011