Pregunta

He estado trabajando en un proyecto ASP.NET que guardará los archivos cargados en un recurso compartido de red. Pensé que podría usar un directorio virtual y estar bien, pero he estado luchando con los permisos para Directory.CreateDirectory.

Pude cargar archivos, así que decidí cambiar mi código para colocar todo en un solo directorio, sin embargo, esto requiere que use File.Exists para evitar sobrescribir duplicados.

Ahora que tengo todo mi código actualizado, he descubierto que no importa lo que haga, File.Exists siempre devuelve falso (el archivo definitivamente existe) cuando pruebo contra el recurso compartido de red.

¿Alguna idea? Estoy llegando al final de mi cuerda con las redes compartidas.

¿Fue útil?

Solución

Recientemente, trabajé en un proyecto muy similar en el que estoy guardando archivos en un recurso compartido de red. Las dos computadoras están en la misma subred, pero no están controladas por el controlador de dominio, por lo que cada computadora tiene sus propios usuarios.

Creé un usuario con el mismo nombre de usuario y contraseña en ambos equipos. Luego creé un recurso compartido de red y configuré los permisos de carpeta / recurso compartido para permitir la lectura y escritura para el usuario.

Luego creé la siguiente clase para administrar la suplantación:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;
using System.Text;

namespace MyProject.Business.Web
{
    public class SecurityManager
    {
        #region DLL Imports
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

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

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
        #endregion

        public string Domain { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }

        private WindowsImpersonationContext m_CurrentImpersonationContext;

        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        public void StartImpersonation()
        {
            const int LOGON32_PROVIDER_DEFAULT = 0;
            const int LOGON32_LOGON_INTERACTIVE = 2;

            IntPtr tokenHandle = IntPtr.Zero;
            IntPtr dupeTokenHandle = IntPtr.Zero;

            // obtain a handle to an access token
            bool wasLogonSuccessful = LogonUser(UserName, Domain, Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle);

            if (!wasLogonSuccessful)
                throw new Exception(String.Format("Logon failed with error number {0}", Marshal.GetLastWin32Error()));

            // use the token handle to impersonate the user
            WindowsIdentity newId = new WindowsIdentity(tokenHandle);
            m_CurrentImpersonationContext = newId.Impersonate();

            // free the tokens
            if (tokenHandle != IntPtr.Zero)
                CloseHandle(tokenHandle);
        }
        public void EndImpersonation()
        {
            m_CurrentImpersonationContext.Undo();
        }
    }
}

Luego, en la página ASP.NET hice lo siguiente:

SecurityManager sm = new SecurityManager();
sm.UserName = ConfigurationManager.AppSettings["UserFileShareUsername"];
sm.Password = ConfigurationManager.AppSettings["UserFileSharePassword"];
sm.StartImpersonation();

if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);

File.Move(sourcePath, destinationPath);

sm.EndImpersonation();

Otros consejos

File.Exist no comprueba realmente la existencia de un archivo. En su lugar, comprueba la existencia de archivos a los que tiene cierto grado de acceso. Si sabe que el archivo existe, el problema probable es que no tiene acceso a él.

Quizás el código que se está ejecutando (es decir, el código del servidor ASP.NET) se esté ejecutando como un usuario (por ejemplo, el usuario de IIS) que no tiene permiso para acceder a ese recurso compartido de red.

Creo que se supone que IIS no debe ejecutarse como un usuario altamente privilegiado, que de forma predeterminada tiene permiso para ver recursos compartidos en otras máquinas.

Utilicé mucho el mismo código, pero mi clase implementó la interfaz IDisposable y agregó el Deshacer () al método Dispose (). Este código funciona bien, si eres el único desarrollador que lo usa y siempre harás las cosas de la manera correcta, ¿no?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top