Natknęliśmy się na interesującą sytuację, która wymaga rozwiązania, a moje wyszukiwania zakończyły się niepowodzeniem. Dlatego apeluję do społeczności SO o pomoc.
Problem jest następujący: musimy programowo uzyskać dostęp do udostępnionego pliku, który nie znajduje się w naszej domenie i nie znajduje się w zaufanej domenie zewnętrznej za pośrednictwem zdalnego udostępniania plików / UNC. Oczywiście musimy dostarczyć poświadczenia do zdalnego komputera.
Zwykle można rozwiązać ten problem na jeden z dwóch sposobów:
- Zamapuj udział plików jako dysk i podaj w tym momencie poświadczenia. Odbywa się to zwykle za pomocą
NET USE
polecenia lub funkcji Win32, które się powielająNET USE
. - Uzyskaj dostęp do pliku ze ścieżką UNC, tak jakby komputer zdalny znajdował się w domenie, i upewnij się, że konto, na którym działa program, jest zduplikowane (łącznie z hasłem) na komputerze zdalnym jako użytkownik lokalny. Zasadniczo należy wykorzystać fakt, że system Windows automatycznie dostarczy poświadczenia bieżącego użytkownika, gdy użytkownik spróbuje uzyskać dostęp do udostępnionego pliku.
- Nie używaj zdalnego udostępniania plików. Użyj FTP (lub innego sposobu), aby przesłać plik, pracuj nad nim lokalnie, a następnie prześlij go z powrotem.
Z różnych i różnych powodów nasi architekci bezpieczeństwa / sieci odrzucili pierwsze dwa podejścia. Drugie podejście to oczywiście luka w zabezpieczeniach; jeśli zdalny komputer jest zagrożony, lokalny komputer jest teraz zagrożony. Pierwsze podejście jest niezadowalające, ponieważ nowo zamontowany dysk jest współdzielonym zasobem dostępnym dla innych programów na komputerze lokalnym podczas uzyskiwania dostępu do plików przez program. Mimo że całkiem możliwe jest uczynienie tego tymczasowym, ich zdaniem nadal jest to dziura.
Są otwarte na trzecią opcję, ale zdalni administratorzy sieci nalegają na SFTP zamiast FTPS, a FtpWebRequest obsługuje tylko FTPS. SFTP jest opcją bardziej przyjazną dla zapory ogniowej i istnieje kilka bibliotek, których mógłbym użyć do tego podejścia, ale wolałbym zmniejszyć moje zależności, jeśli mogę.
Przeszukałem MSDN pod kątem zarządzanego lub win32 sposobu korzystania ze zdalnego udostępniania plików, ale nie udało mi się znaleźć niczego użytecznego.
Pytam więc: czy jest inny sposób? Czy przegapiłem super tajną funkcję win32, która robi to, czego chcę? A może muszę skorzystać z opcji 3?
źródło
Odpowiedzi:
Sposobem rozwiązania problemu jest użycie interfejsu API Win32 o nazwie WNetUseConnection .
Użyj tej funkcji, aby połączyć się ze ścieżką UNC z uwierzytelnianiem, a NIE do mapowania dysku .
Umożliwi to połączenie się ze zdalnym komputerem, nawet jeśli nie znajduje się on w tej samej domenie, a nawet jeśli ma inną nazwę użytkownika i hasło.
Po użyciu WNetUseConnection będziesz mógł uzyskać dostęp do pliku za pośrednictwem ścieżki UNC, tak jakbyś był w tej samej domenie. Najlepszym sposobem jest prawdopodobnie użycie wbudowanych udziałów administracyjnych.
Przykład: \\ nazwa_komputera \ c $ \ program files \ Folder \ file.txt
Oto przykładowy kod C #, który używa WNetUseConnection.
Uwaga: w przypadku NetResource należy przekazać null dla lpLocalName i lpProvider. Typ dwType powinien mieć wartość RESOURCETYPE_DISK. Nazwa lpRemoteName powinna mieć wartość \\ nazwa_komputera.
źródło
WNetUseConnection
należy zamykać ręcznie, dzwoniącWNetCancelConnection2
? A może istnieje limit czasu bezczynności (lub jakiś inny mechanizm) i nie musimy się tym przejmować?Dla osób szukających szybkiego rozwiązania możesz skorzystać z
NetworkShareAccesser
napisanego przeze mnie niedawno (na podstawie tej odpowiedzi (wielkie dzięki!)):Stosowanie:
UWAGA: Należy bezwzględnie, że
Dispose
zNetworkShareAccesser
nazywany jest (nawet jeśli app awarii!), W przeciwnym razie otwarte połączenie pozostanie w systemie Windows. Możesz zobaczyć wszystkie otwarte połączenia, otwierająccmd
monit i wpisującnet use
.Kod:
źródło
using System.Runtime.InteropServices;
iusing System.ComponentModel;
dlaDllImport
iWin32Exception
AFAIK, nie musisz mapować ścieżki UNC na literę dysku, aby ustanowić poświadczenia dla serwera. Regularnie korzystałem ze skryptów wsadowych, takich jak:
Jednak każdy program działający na tym samym koncie co Twój program nadal miałby dostęp do wszystkiego, do czego
username:password
ma dostęp. Możliwym rozwiązaniem może być odizolowanie programu na jego własnym lokalnym koncie użytkownika (dostęp UNC jest lokalny dla konta, które wywołałoNET USE
).Uwaga: korzystanie z SMB w różnych domenach nie jest dobrym zastosowaniem technologii IMO. Jeśli bezpieczeństwo jest tak ważne, fakt, że SMB nie ma szyfrowania, sam w sobie trochę utrudnia.
źródło
NET USE
, może to być opłacalne podejście. Czy na pewno jednak musimy korzystać z konta lokalnego? CzyNET USE
połączenie nie byłoby lokalne dla komputera, na którym zostało wywołane? Dałeś mi dobrą ścieżkę badawcząZamiast WNetUseConnection poleciłbym NetUseAdd . WNetUseConnection to starsza funkcja, która została zastąpiona przez WNetUseConnection2 i WNetUseConnection3, ale wszystkie te funkcje tworzą urządzenie sieciowe, które jest widoczne w Eksploratorze Windows. NetUseAdd jest odpowiednikiem wywołania net use w monicie DOS w celu uwierzytelnienia na zdalnym komputerze.
Jeśli wywołasz NetUseAdd, kolejne próby uzyskania dostępu do katalogu powinny się powieść.
źródło
Chociaż sam nie wiem, z pewnością mam nadzieję, że numer 2 jest nieprawidłowy ... Chciałbym pomyśleć, że system Windows nie będzie AUTOMATYCZNIE podawać moich danych logowania (a najmniej mojego hasła!) Do żadnego komputera , a co dopiero takiego, który nie jest częścią mojego zaufania.
Niezależnie od tego, czy poznałeś architekturę personifikacji? Twój kod będzie wyglądał podobnie do tego:
W tym przypadku
token
zmienną jest IntPtr. Aby uzyskać wartość tej zmiennej, musisz wywołać niezarządzaną funkcję LogonUser Windows API. Szybka wycieczka do pinvoke.net daje nam następujący podpis:Nazwa użytkownika, domena i hasło powinny wydawać się dość oczywiste. Przyjrzyj się różnym wartościom, które można przekazać do dwLogonType i dwLogonProvider, aby określić, która najlepiej odpowiada Twoim potrzebom.
Ten kod nie został przetestowany, ponieważ nie mam tutaj drugiej domeny, w której mógłbym zweryfikować, ale mam nadzieję, że to powinno skierować Cię na właściwą ścieżkę.
źródło
Tutaj minimalna klasa POC ze wszystkimi usuniętymi okruchami
Możesz bezpośrednio użyć
\\server\share\folder
w /WNetUseConnection
, nie ma potrzeby rozbierania go\\server
tylko wcześniej.źródło
Większość serwerów SFTP obsługuje również SCP, co może być o wiele łatwiejsze do znalezienia bibliotek. Możesz nawet zadzwonić do istniejącego klienta z kodu, takiego jak pscp dołączony do PuTTY .
Jeśli typ pliku, z którym pracujesz, jest czymś prostym, jak plik tekstowy lub XML, możesz nawet posunąć się do napisania własnej implementacji klient / serwer w celu manipulowania plikiem za pomocą czegoś takiego jak .NET Remoting lub usługi sieciowe.
źródło
Widziałem opcję 3 zaimplementowaną za pomocą narzędzi JScape w dość prosty sposób. Możesz spróbować. To nie jest darmowe, ale spełnia swoje zadanie.
źródło
im dołączyć mój kod vb.net na podstawie odniesienia Brian
Jak tego użyć
źródło
Szukałem do stwardnienia rozsianego, aby znaleźć odpowiedzi. Pierwsze rozwiązanie zakłada, że konto użytkownika uruchamiającego proces aplikacji ma dostęp do udostępnionego folderu lub dysku (ta sama domena). Upewnij się, że Twój DNS został rozwiązany lub spróbuj użyć adresu IP. Po prostu wykonaj następujące czynności:
Jeśli chcesz korzystać z różnych domen .NET 2.0 z poświadczeniami, postępuj zgodnie z tym modelem:
źródło