Pergunta

Eu tenho trabalhado em um projeto ASP.NET que está indo para salvar os arquivos enviados para um compartilhamento de rede. Eu percebi que eu poderia usar apenas um diretório virtual e ficar bem, mas eu tenho lutado com permissões para Directory.CreateDirectory.

Eu era capaz de fazer upload de arquivos, então eu decidi mudar o meu código para colocar tudo em um único diretório, no entanto, isso me obriga a fazer uso de File.Exists para evitar a substituição duplicatas.

Agora que eu tenho todo o meu código atualizado, eu descobri que não importa o que eu faço, File.Exists sempre retorna false (O arquivo definitivamente existe) quando eu teste contra o compartilhamento de rede.

Todas as idéias? Estou chegando até o fim da minha corda com compartilhamentos de rede.

Foi útil?

Solução

Eu só recentemente trabalhou em um projeto muito semelhante onde eu estou salvando os arquivos para um compartilhamento de rede. Os dois computadores estão na mesma sub-rede, mas não são controlados pelo controlador de domínio, de modo que cada computador tem seu próprio usuários.

Eu criei um usuário com o mesmo nome de usuário e senha em ambos os computadores. Então eu criei um compartilhamento de rede e definir as permissões de compartilhamento / pasta para permitir leitura e escrita para o usuário.

Então, criamos a seguinte classe para gerenciar a representação:

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();
        }
    }
}

Em seguida, na página ASP.NET eu fiz o seguinte:

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();

Outras dicas

File.Exist na verdade não verificar se há existência de um arquivo. Em vez disso verifica existência de arquivos que você tem alguma medida de acesso. Se você conhece o arquivo existe, o problema provável é que você não tem acesso a ele.

Talvez o código que está em execução (ou seja, código do servidor ASP.NET) está sendo executado como um usuário (por exemplo, o usuário IIS) que não tem permissão para acessar esse compartilhamento de rede.

Eu acho que o IIS não é suposto para ser executado como um usuário altamente privilegiado, que por padrão tem permissão para visualizar ações em outras máquinas.

Eu usei muito o mesmo código, mas tinha minha classe implementar a interface IDisposable, e adicionado a Undo () para o método Dispose (). Este código fina funciona, se você é o único desenvolvedor usá-lo e você vai sempre fazer as coisas da maneira certa, certo?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top