Ao conectar-se a um compartilhamento de rede para o qual o usuário atual (no meu caso, um usuário de serviço habilitado para rede) não tem direitos, é necessário fornecer nome e senha.
Eu sei como fazer isso com as funções Win32 (a WNet*
família de mpr.dll
), mas gostaria de fazê-lo com a funcionalidade .Net (2.0).
Quais opções estão disponíveis?
Talvez mais algumas informações ajudem:
- O caso de uso é um serviço do Windows, não um aplicativo Asp.Net.
- O serviço está sendo executado em uma conta que não possui direitos sobre o compartilhamento.
- A conta de usuário necessária para o compartilhamento não é conhecida no lado do cliente.
- Cliente e servidor não são membros do mesmo domínio.
Respostas:
Você pode alterar a identidade do encadeamento ou P / Invoke WNetAddConnection2. Prefiro o último, pois às vezes preciso manter várias credenciais para diferentes locais. Envolvo-o em um IDisposable e chamo WNetCancelConnection2 para remover os creds posteriormente (evitando o erro de vários nomes de usuário):
fonte
Gostei tanto da resposta de Mark Brackett que fiz minha própria implementação rápida. Aqui está, se mais alguém precisar com pressa:
fonte
throw new Win32Exception(result);
, desde WNetAddConnection2 retornos win32 códigos de erro (ERROR_XXX
)NetworkCredential
objeto, o aplicativo conseguiu se conectar uma vez à unidade de rede. Depois disso, obtivemos um ERROR_LOGON_FAILURE em cada tentativa até que o aplicativo fosse reiniciado. Tentamos também fornecer o domínio noNetworkCredential
objeto, e de repente ele funcionou! Não faço ideia por que isso resolveu o problema, especialmente o fato de ele ter se conectado uma vez sem o domínio.Hoje, sete anos depois, estou enfrentando o mesmo problema e gostaria de compartilhar minha versão da solução.
Está pronto para copiar e colar :-) Aqui está:
Passo 1
No seu código (sempre que você precisar fazer algo com permissões)
Passo 2
O arquivo Helper que faz uma mágica
fonte
Eu pesquisei muitos métodos e fiz do meu jeito. Você deve abrir uma conexão entre duas máquinas via prompt de comando NET USE e, após concluir o trabalho, limpe a conexão com o prompt de comando NET USE "myconnection" / delete.
Você deve usar o processo do Prompt de Comando do código por trás desta maneira:
O uso é simples:
Aqui estão as funções:
E também a função ExecuteCommand é:
Essas funções funcionaram muito rápido e estável para mim.
fonte
A solução Luke Quinane parece boa, mas funcionou apenas parcialmente no meu aplicativo ASP.NET MVC. Tendo dois compartilhamentos no mesmo servidor com credenciais diferentes, eu poderia usar a representação apenas para o primeiro.
O problema com o WNetAddConnection2 também é que ele se comporta de maneira diferente em diferentes versões do Windows. Por isso, procurei alternativas e encontrei a função LogonUser . Aqui está o meu código que também funciona no ASP.NET:
Uso:
fonte
Para VB.lovers, o equivalente em VB.NET do código de Luke Quinane (obrigado Luke!)
fonte
Uma opção que pode funcionar é usar
WindowsIdentity.Impersonate
(e alterar o principal do encadeamento) para se tornar o usuário desejado, assim . De volta a p / invocar, no entanto, eu tenho medo ...Outra opção atrevida (e igualmente longe do ideal) pode ser gerar um processo para fazer o trabalho ...
ProcessStartInfo
aceita a.UserName
,.Password
e.Domain
.Finalmente - talvez execute o serviço em uma conta dedicada que tenha acesso?(removido porque você esclareceu que isso não é uma opção).fonte
OK ... eu posso voltar ..
Disclaimer: Acabei de ter um dia com mais de 18 horas (de novo) .. Estou velho e esquecido .. Não sei soletrar .. Tenho um curto período de atenção, por isso é melhor responder rapidamente .. :-)
Questão:
É possível alterar o objeto principal do segmento para um usuário sem conta na máquina local?
Responda:
Sim, você pode alterar uma entidade de segmento, mesmo que as credenciais que você está usando não estejam definidas localmente ou estejam fora da "floresta".
Eu acabei de encontrar esse problema ao tentar conectar-me a um servidor SQL com autenticação NTLM de um serviço. Essa chamada usa as credenciais associadas ao processo, o que significa que você precisa de uma conta local ou uma conta de domínio para se autenticar antes de poder se representar. Blá, blá ...
Mas...
Chamar LogonUser (..) com o atributo ???? _ NEW_CREDENTIALS retornará um token de segurança sem tentar autenticar as credenciais. Kewl .. Não é necessário definir a conta na "floresta". Depois de ter o token, você poderá chamar DuplicateToken () com a opção de habilitar a representação, resultando em um novo token. Agora chame SetThreadToken (NULL, token); (Pode ser um token?) .. Uma chamada para ImpersonateLoggedonUser (token); pode ser necessário, mas acho que não. Procure..
Faça o que você precisa fazer..
Chame RevertToSelf () se você chamou ImpersonateLoggedonUser () e SetThreadToken (NULL, NULL); (Eu acho ... procure) e, em seguida, CloseHandle () nas alças criadas.
Sem promessas, mas isso funcionou para mim ... Isso está no topo da minha cabeça (como meu cabelo) e não sei soletrar !!!
fonte
Se você não conseguir criar um token de segurança válido localmente, parece que descartou todas as opções da API Win32 e WNetAddConnection * da barra de opções.
Toneladas de informações no MSDN sobre WNet - informações do PInvoke e código de exemplo que se conecta a um caminho UNC aqui:
Referência do MSDN aqui:
fonte
Também portado para F # para usar com FAKE
fonte
Você deve adicionar algo parecido com isto:
No seu web.config.
Mais Informações.
fonte