通过指定凭证访问服务器上的文件

我们公司有一个共享点文件服务器,UNC的外观如下所示: theserver.ourdomain.com rootdirectory

目前,该驱动器已映射到本地计算机上的Z:。 要访问Z:你必须指定(每次登录时)证书(在我们的例子是我们的用户名和密码登录,我们上)来访问文件夹和文件在rootdirectory。

我处于需要将文件复制到共享点服务器上的情况。 我希望能够在不使用映射网络驱动器的情况下将文件复制到服务器上(不必在路径中指定Z:)。 我如何提供证书,以便我可以执行基本IO函数,如GetDirectories(),GetFiles(),IO.File.Copy()等...?

我已经研究了以下内容,但未能成功实施:

  • LogonUser API通过指定纯文本用户名和密码进行调用,然后从该调用中获取令牌并使用WindowsIdentity类的新实例模拟该用户。 能够获得令牌,但模拟似乎不起作用。 保持访问被拒绝的错误。
  • CredUIPromptForCredentials / CredUIPromptForWindowsCredentials API调用,但我意识到这些只是一个花哨的Windows用户界面,您可以在其中输入凭据并实际上不会执行任何操作。

    <DllImport("advapi32.dll", SetLastError:=True)> _
    Private Shared Function LogonUser(lpszUsername As String, lpszDomain As String, _
                                              lpszPassword As String, dwLogonType As Integer, _
                                              dwLogonProvider As Integer, ByRef phToken As IntPtr) As Boolean
    End Function
    
    <DllImport("kernel32.dll", CharSet:=CharSet.Auto)> _
    Private Shared Function CloseHandle(handle As IntPtr) As Boolean
    End Function
    
    '// logon types
    Public Const LOGON32_LOGON_NETWORK As Integer = 3
    Public Const LOGON32_LOGON_NEW_CREDENTIALS As Integer = 9
    
    '// logon providers
    Public Const LOGON32_PROVIDER_WINNT50 As Integer = 3
    Public Const LOGON32_PROVIDER_WINNT40 As Integer = 2
    Public Const LOGON32_PROVIDER_WINNT35 As Integer = 1
    Public Const LOGON32_PROVIDER_DEFAULT As Integer = 0
    
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Dim token = IntPtr.Zero
        Dim success = LogonUser("username", "domain", "password", _
                                LOGON32_LOGON_NEW_CREDENTIALS, _
                                LOGON32_PROVIDER_DEFAULT, token)
    
        If Not success Then
            Me.RaiseLastWin32Error()
        End If
    
        Using identity = New WindowsIdentity(token)
            Using impersonated = identity.Impersonate()
                Try
                    Dim info = New DirectoryInfo("theserver.ourdomain.comrootdirectory")
                    Dim files = info.GetDirectories()
                Catch ex As Exception
                Finally
                    impersonated.Undo()
                End Try
                If Not CloseHandle(token) Then
                    Me.RaiseLastWin32Error()
                End If
            End Using
        End Using
    
    End Sub
    
    Private Sub RaiseLastWin32Error()
        Dim hr = Marshal.GetLastWin32Error()
        Dim ex = Marshal.GetExceptionForHR(hr)
    
        If ex IsNot Nothing Then
            Throw ex
        End If
        Throw New SystemException(String.Format("Call resulted in error code {0}", hr))
    End Sub
    

  • 这不是对你的问题的直接回答,因为它是一个非常不同的方法。 如果它不适合您的情况很抱歉打扰,但您是否考虑过使用SharePoint Web服务来加载文件和检索信息?

    我建议这种方法有几个原因:

  • 您遇到的问题可能正在发生,因为SharePoint实现的WebDav可能不与System.IO 100%兼容。 我不是内脏方面的专家,我不清楚兼容性,但似乎是合理的。
  • 您拥有的UNC位置可以轻松地转换为Web服务所需的URL。
  • 您可以直接在代理上设置凭据,并且可能会有更简单的时间。 (尽管我们从另一个Web服务器进行这些调用,因此示例中的应用程序池凭证对我们来说已经足够了)
  • 以下是一些经过清理和简化的代码,以防万一:

    // location takes the form http://server.name.com/site/library/folder/document.ext
    
    public string UploadDocument(string location, byte[] fileContents)
    {
        var result = String.empty;
        var destination = new string[1];
        destination[0] = location;
        var fileName = Path.GetFileName(location);
        var fieldInfo = new FieldInformation[0];
        CopyResult[] copyResults;
    
        _copyService.Url = "http://server.name.com/_vti_bin/Copy.asmx";
        _copyService.Credentials = CredentialCache.DefaultCredentials;
        _copyService.CopyIntoItems(fileName, destination, fieldInfo, fileContents, out copyResults);
    
        var errorCode = copyResults[0].ErrorCode;
        if (errorCode != CopyErrorCode.Success)
        {
            if (errorCode == CopyErrorCode.DestinationCheckedOut)
                result = "File is currently checked out. Please try again later.";
            else
                result = "Error uploading content.";
        }
    
        return result;
    }
    

    _copyService是我们注入的依赖项,其中运行时实现是由Visual Studio工具从Copy.asmx SharePoint Web服务生成的代理。

    您还可以使用Lists.asmx Web服务获取文件夹内容和文档元数据。 这种方法最大的缺点是查询信息需要一些CAML的知识和处理结果并不容易。 但是这些服务在MSDN上合理记录,操作都在我们的应用程序中运行。


    那么,我可以在WNetAddConnection2 API的帮助下解决这个问题。 此API还用于映射网络驱动器,但是您可以调用此方法而不指定驱动器号,以便只添加连接。

    比如说你有驱动器X:映射到 server share也可以说它需要用户名和密码来访问服务器上的文件。 当您重新启动Windows 7时,您可能会失去该连接(您将收到一条通知,指出Windows无法重新连接某些网络驱动器)。 如果您有一个需要访问该服务器文件的应用程序,并且您尝试访问该应用程序而不提供您的凭据,您将获得访问被拒绝的例外。 如果你成功地调用了WNetAddConnection2,它不仅可以修复未映射的网络驱动器,还可以通过System.IO命名空间访问这些文件/目录。

    我们使用Sharepoint,并为我工作。 感谢其他人的回复。

    链接地址: http://www.djcxy.com/p/44173.html

    上一篇: Accessing Files On Server By Specifying Credentials

    下一篇: Search and get file information from remote workstation on a Windows domain