VB.NET - Как программно передать аутентификацию на сервер - Как получить доступ к файлам на сервере, который требует аутентификации - PullRequest
0 голосов
/ 01 апреля 2019

Моя цель:

Я пытаюсь получить доступ к диску C на сервере в нашей сети с целью поиска определенного расширения файла и возврата путей к этим файлам. Я нашел код здесь , который отлично работает, но только если я ищу на своем локальном компьютере или IP-адрес сервера, на котором я уже прошел аутентификацию; когда я пытаюсь запустить код для IP-адреса сервера, который я не аутентифицировал, он не работает.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Cursor = Cursors.WaitCursor
    DirSearch("\\10.0.15.87\c$")
    Cursor = Cursors.Default
End Sub

Public Sub DirSearch(ByVal sDir As String)
    Try
        For Each dir As String In Directory.GetDirectories(sDir)
            For Each file In Directory.GetFiles(dir, "myfile.extension")
                MsgBox(file)
            Next
            DirSearch(dir)
        Next
    Catch ex As Exception
        Debug.WriteLine(ex.Message)
    End Try
End Sub

Когда я запускаю код:

Я считаю, что код выполняется до завершения; Курсор превращается в WaitCursor примерно на полсекунды, а затем возвращается в нормальное состояние, после чего ошибки не выдаются, и все продолжается как обычно. Если я изменю «10.0.15.87» на «10.0.15.81» (который я уже аутентифицировал вручную), я получу несколько всплывающих окон MsgBox с путями к файлам. (Я уверен, что проблема не в поиске файла, я знаю, что он работает для других ip и что файлы, которые я ищу, находятся на диске c 10.0.15.87 - я считаю, что мне просто нужно пройти аутентификацию. )

Вот что происходит, когда я пытаюсь перейти к ip 87 вручную:

enter image description here

Информация о 10.0.15.87:

  • Он не подключен к домену в отличие от компьютера, с которого я запускаю код. (Не 10.0.15.81)
  • У него статический ip
  • Если я попытаюсь получить к нему доступ вручную, я могу ввести учетные данные в соответствии с изображением выше, мне просто нужно передать учетные данные через код.

Как пройти аутентификацию перед попыткой доступа к серверу?

1 Ответ

0 голосов
/ 02 апреля 2019

В конце концов я нашел метод, который работал для моих нужд и настройки сети, но по пути я также нашел другой метод, который проще и может работать для других, поэтому я поделюсь им тоже.

Метод 1 - Использование функций в MPR.DLL

В конце концов я нашел этот ответ на другой вопрос. Это метод, который работал для меня. Вот как это выглядит в моем проекте:

Imports System.IO    
Imports System.Runtime.InteropServices

Public Class Form1 
    Dim user As String
    Dim pass As String
    Dim path As String

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Cursor = Cursors.WaitCursor
        user = "UsernameString"
        pass = "PasswordString"
        path = "\\10.0.15.87\c$"
        MPRAuth()
        DirSearch(path)
        Cursor = Cursors.Default
    End Sub

    Private Sub MPRAuth()
        Dim nr As New NETRESOURCE
        nr.dwType = RESOURCETYPE_DISK
        nr.lpRemoteName = path
        If WNetAddConnection2(nr, pass, user, 0) <> NO_ERROR Then
            Throw New Exception("WNetAddConnection2 failed.")
        End If
        If WNetCancelConnection2(path, 0, True) <> NO_ERROR Then
            Throw New Exception("WNetCancelConnection2 failed.")
        End If
    End Sub

    Public Sub DirSearch(ByVal sDir As String)
        Try
            For Each dir As String In Directory.GetDirectories(sDir)
                Try
                    For Each file In Directory.GetFiles(dir, "*.exe")
                        MsgBox(file)
                    Next
                Catch ex As Exception
                    Debug.WriteLine(ex.Message)
                End Try
                DirSearch(dir)
            Next
        Catch ex As Exception
            Debug.WriteLine(ex.Message)
        End Try
    End Sub

    <StructLayout(LayoutKind.Sequential)>
    Private Structure NETRESOURCE
        Public dwScope As UInteger
        Public dwType As UInteger
        Public dwDisplayType As UInteger
        Public dwUsage As UInteger
        <MarshalAs(UnmanagedType.LPTStr)>
        Public lpLocalName As String
        <MarshalAs(UnmanagedType.LPTStr)>
        Public lpRemoteName As String
        <MarshalAs(UnmanagedType.LPTStr)>
        Public lpComment As String
        <MarshalAs(UnmanagedType.LPTStr)>
        Public lpProvider As String
    End Structure

    Private Const NO_ERROR As UInteger = 0
    Private Const RESOURCETYPE_DISK As UInteger = 1

    <DllImport("mpr.dll", CharSet:=CharSet.Auto)>
    Private Shared Function WNetAddConnection2(ByRef lpNetResource As NETRESOURCE, <[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpPassword As String, <[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpUserName As String, ByVal dwFlags As UInteger) As UInteger
    End Function

    <DllImport("mpr.dll", CharSet:=CharSet.Auto)>
    Private Shared Function WNetCancelConnection2(<[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpName As String, ByVal dwFlags As UInteger, <MarshalAs(UnmanagedType.Bool)> ByVal fForce As Boolean) As UInteger
    End Function
End Class

Метод 2 - NetworkCredential и CredentialCache

Этот метод преобразует ip в URI и кэширует учетные данные. Мне не удалось заставить этот метод работать с сервером в другом домене, чем я.

Imports System.Net

Dim builder As New UriBuilder("10.0.15.87")
Dim uri As Uri = builder.Uri
Dim netCred = New NetworkCredential("UsernameString", "PasswordString", "DomainString")
Dim netCache = New CredentialCache()
netCache.Add(uri, "Basic", netCred)
DirSearch("\\10.0.15.87\c$")

Метод 2 гораздо менее сложен, чем метод 1, и он работал нормально для меня, пока сервер, к которому я пытался подключиться, находился в том же домене, что и я. Когда я попытался подключиться к серверу, не входящему в домен, я получил ошибку «Неверное имя пользователя или пароль», что не соответствует действительности, поэтому я не уверен, где была проблема - возможно, кто-то другой знает. Метод 1 до сих пор работал для меня безупречно для любого сервера, независимо от того, был ли домен или если он был аутентифицирован на нем перед запуском кода. Надеюсь, это поможет другим!

...