Bir ağ paylaşımına bağlanırken kullanıcı adı ve parola nasıl sağlanır


191

Geçerli kullanıcının (benim durumumda, ağ destekli bir hizmet kullanıcısı) hiçbir hakkı, adı ve parolası bulunmayan bir ağ paylaşımına bağlanırken.

Win32 işlevleriyle ( WNet*aileden mpr.dll) bunu nasıl yapacağımı biliyorum , ancak .Net (2.0) işlevselliği ile yapmak istiyorum.

Hangi seçenekler mevcut?

Belki biraz daha fazla bilgi yardımcı olabilir:

  • Kullanım durumu bir Asp.Net uygulaması değil, bir Windows hizmetidir.
  • Hizmet, paylaşım üzerinde hakları olmayan bir hesap altında çalışıyor.
  • Paylaşım için gereken kullanıcı hesabı istemci tarafında bilinmiyor.
  • İstemci ve sunucu aynı etki alanının üyesi değil.

7
Sana yararlı bir cevap vermeme rağmen, bir anti-cevap sağlayabiliyorum. iki alan. Bir güven varsa, o zaman işe yarayacağını düşünüyorum. Sadece Marc'ın bir yorum olarak cevap olurdu ama yorum yapmak için yeterli temsilcisi yok. : - /
Moose

Yanıtlar:


152

İş parçacığı kimliğini veya P / Invoke WNetAddConnection2 öğesini değiştirebilirsiniz. İkincisini tercih ederim, çünkü bazen farklı yerler için birden fazla kimlik bilgisi tutmam gerekir. Ben bir IDisposable içine sarın ve daha sonra (birden çok kullanıcı adı hatası kaçınarak) kredileri kaldırmak için WNetCancelConnection2 çağırır:

using (new NetworkConnection(@"\\server\read", readCredentials))
using (new NetworkConnection(@"\\server2\write", writeCredentials)) {
   File.Copy(@"\\server\read\file", @"\\server2\write\file");
}

4
Hizmet hedef etki alanının üyesi değil; güvenlik jetonunu yerel olarak oluşturamayacağınız ve onunla kimliğe bürünemeyeceğiniz için kimliğe bürünme çalışamaz. PInvoke tek yoldur.
stephbu

@MarkBrackett Bunun eski bir cevap olduğunu biliyorum, ama belki de hala biliyorsunuz ... erişim sadece programa mı yoksa explorer aracılığıyla giriş yapan kullanıcıya da verilecek mi?
Breeze

@Breeze - Ben test etmedim, ama oturum açma oturumu için kimlik doğrulaması beklenir; yani programınız oturum açmış kullanıcı olarak çalışıyorsa, erişim de olurdu (en azından işlem süresince).
Mark Brackett

8
ReadCredentials ve writeCredentials tanımları cevaba dahil edilebilir.
Anders Lindén

2
Eğer alıyorsanız Hatası 53 , emin yolu bir "\" ile biten değil yapmak
Mustafa S.

327

Ben sevdim Mark Brackett bu kadar ben kendi hızlı uygulanmasını yaptığını cevabını. İşte acele başka birinin ihtiyacı varsa:

public class NetworkConnection : IDisposable
{
    string _networkName;

    public NetworkConnection(string networkName, 
        NetworkCredential credentials)
    {
        _networkName = networkName;

        var netResource = new NetResource()
        {
            Scope = ResourceScope.GlobalNetwork,
            ResourceType = ResourceType.Disk,
            DisplayType = ResourceDisplaytype.Share,
            RemoteName = networkName
        };

        var userName = string.IsNullOrEmpty(credentials.Domain)
            ? credentials.UserName
            : string.Format(@"{0}\{1}", credentials.Domain, credentials.UserName);

        var result = WNetAddConnection2(
            netResource, 
            credentials.Password,
            userName,
            0);

        if (result != 0)
        {
            throw new Win32Exception(result);
        }   
    }

    ~NetworkConnection()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        WNetCancelConnection2(_networkName, 0, true);
    }

    [DllImport("mpr.dll")]
    private static extern int WNetAddConnection2(NetResource netResource, 
        string password, string username, int flags);

    [DllImport("mpr.dll")]
    private static extern int WNetCancelConnection2(string name, int flags,
        bool force);
}

[StructLayout(LayoutKind.Sequential)]
public class NetResource
{
    public ResourceScope Scope;
    public ResourceType ResourceType;
    public ResourceDisplaytype DisplayType;
    public int Usage;
    public string LocalName;
    public string RemoteName;
    public string Comment;
    public string Provider;
}

public enum ResourceScope : int
{
    Connected = 1,
    GlobalNetwork,
    Remembered,
    Recent,
    Context
};

public enum ResourceType : int
{
    Any = 0,
    Disk = 1,
    Print = 2,
    Reserved = 8,
}

public enum ResourceDisplaytype : int
{
    Generic = 0x0,
    Domain = 0x01,
    Server = 0x02,
    Share = 0x03,
    File = 0x04,
    Group = 0x05,
    Network = 0x06,
    Root = 0x07,
    Shareadmin = 0x08,
    Directory = 0x09,
    Tree = 0x0a,
    Ndscontainer = 0x0b
}

10
Gerçekten olmalı throw new Win32Exception(result);, çünkü WNetAddConnection2 win32 hata kodlarını döndürür ( ERROR_XXX)
torvin

2
Bu küçük bir kod parçası. Bir MVC5 web uygulamasına yazdırmak üzere bir dizin listesi almak için UNIX sisteminde oturum açmak gerekiyordu ve bu hile yaptı. 1 !!!
Tay

3
Yukarıdaki kodun derlenmesi için aşağıdaki kullanma ifadeleri gereklidir: using System.Net; System.Runtime.InteropServices kullanarak; System.ComponentModel kullanarak;
Matt Nelson

4
eski iş parçacığını yenilediğim için üzgünüm, ama blok bittikten sonra bağlantıyı kapatmıyor gibi görünüyor Birkaç resim yüklemek için bir programım var, birincisi iyi gidiyor, ikincisi başarısız oluyor. Program kapatıldığında bağlantı kesilir. Herhangi bir tavsiye?
arti

3
Sizinle aynı sorunu yaşadık, @ arti. NetworkCredentialNesne üzerindeki kullanıcı adını ve parolayı ayarlayarak uygulama bir kez ağ sürücüsüne bağlanabildi. Bundan sonra , uygulama yeniden başlatılana kadar her denemede bir ERROR_LOGON_FAILURE aldık . Daha sonra NetworkCredentialnesneyi de alan üzerinde sağlamaya çalıştık ve aniden işe yaradı! Bunun neden sorunu çözdüğüne dair hiçbir fikrim yok, özellikle de etki alanı olmadan bir kez bağlantı kurmaya çalıştığı gerçeği.
lsmeby

50

Bugün 7 yıl sonra aynı sorunla karşı karşıyayım ve çözümün versiyonunu paylaşmak istiyorum.

Kopyala ve yapıştırmaya hazır :-) İşte burada:

Aşama 1

Kodunuzda (izinlerle bir şey yapmanız gerektiğinde)

ImpersonationHelper.Impersonate(domain, userName, userPassword, delegate
                            {
                                //Your code here 
                                //Let's say file copy:
                                if (!File.Exists(to))
                                {
                                    File.Copy(from, to);
                                }
                            });

Adım 2

Bir sihir yapan yardımcı dosya

using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;    
using Microsoft.Win32.SafeHandles;


namespace BlaBla
{
    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafeTokenHandle()
            : base(true)
        {
        }

        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);

        protected override bool ReleaseHandle()
        {
            return CloseHandle(handle);
        }
    }

    public class ImpersonationHelper
    {
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
        int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private extern static bool CloseHandle(IntPtr handle);

        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        public static void Impersonate(string domainName, string userName, string userPassword, Action actionToExecute)
        {
            SafeTokenHandle safeTokenHandle;
            try
            {

                const int LOGON32_PROVIDER_DEFAULT = 0;
                //This parameter causes LogonUser to create a primary token.
                const int LOGON32_LOGON_INTERACTIVE = 2;

                // Call LogonUser to obtain a handle to an access token.
                bool returnValue = LogonUser(userName, domainName, userPassword,
                    LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                    out safeTokenHandle);
                //Facade.Instance.Trace("LogonUser called.");

                if (returnValue == false)
                {
                    int ret = Marshal.GetLastWin32Error();
                    //Facade.Instance.Trace($"LogonUser failed with error code : {ret}");

                    throw new System.ComponentModel.Win32Exception(ret);
                }

                using (safeTokenHandle)
                {
                    //Facade.Instance.Trace($"Value of Windows NT token: {safeTokenHandle}");
                    //Facade.Instance.Trace($"Before impersonation: {WindowsIdentity.GetCurrent().Name}");

                    // Use the token handle returned by LogonUser.
                    using (WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
                    {
                        using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
                        {
                            //Facade.Instance.Trace($"After impersonation: {WindowsIdentity.GetCurrent().Name}");
                            //Facade.Instance.Trace("Start executing an action");

                            actionToExecute();

                            //Facade.Instance.Trace("Finished executing an action");
                        }
                    }
                    //Facade.Instance.Trace($"After closing the context: {WindowsIdentity.GetCurrent().Name}");
                }

            }
            catch (Exception ex)
            {
                //Facade.Instance.Trace("Oh no! Impersonate method failed.");
                //ex.HandleException();
                //On purpose: we want to notify a caller about the issue /Pavel Kovalev 9/16/2016 2:15:23 PM)/
                throw;
            }
        }
    }
}

2
@MohammadRashid LogonUser'daki belgelere göre , yalnızca yerel bilgisayardaki kullanıcılar için çalışır: "LogonUser işlevi, bir kullanıcıyı yerel bilgisayarda oturum açmaya çalışır. Yerel bilgisayar, LogonUser'ın çağrıldığı bilgisayardır. "Bir hata iletisi alırsınız" Win32Exception: Kullanıcı adı veya parola yanlış. " Bu yüzden makinelerin en azından aynı alanda olması gerektiğini düşünüyorum.
Charles Chen

1
@CharlesChen Bunun etki alanlarında iyi çalıştığını kanıtladım, FYI. Bunu çalıştırdığım sunucu bir DMZ'de ve kesinlikle bir güvenlik duvarı üzerinden farklı bir etki alanındaki bir dosya sunucusuna bağlanıyor. Katil pasajı Pavel, sen erkeksin ve bu muhtemelen bugün kabul edilen cevap olmalı.
Brian MacKay

Bu harika bir çözüm! Teşekkürler Pavel Kovalev.
STLDev

bu ldap üzerinde çalışıyor mu? kullanılabilir bir oturum açma sunucum yok diyor. im kullanarak ldap auth
Julius Limson

28

Birçok yöntem aradım ve kendi yöntemimle yaptım. Komut istemi NET USE komutu ile iki makine arasında bir bağlantı açmanız ve çalışmanızı bitirdikten sonra NET USE "myconnection" / delete komut istemi ile bağlantıyı temizlemeniz gerekir.

Komut İstemi işlemini aşağıdaki koddan aşağıdaki gibi kullanmalısınız:

var savePath = @"\\servername\foldername\myfilename.jpg";
var filePath = @"C:\\temp\myfileTosave.jpg";

Kullanımı basit:

SaveACopyfileToServer(filePath, savePath);

İşte fonksiyonlar:

using System.IO
using System.Diagnostics;


public static void SaveACopyfileToServer(string filePath, string savePath)
    {
        var directory = Path.GetDirectoryName(savePath).Trim();
        var username = "loginusername";
        var password = "loginpassword";
        var filenameToSave = Path.GetFileName(savePath);

        if (!directory.EndsWith("\\"))
            filenameToSave = "\\" + filenameToSave;

        var command = "NET USE " + directory + " /delete";
        ExecuteCommand(command, 5000);

        command = "NET USE " + directory + " /user:" + username + " " + password;
        ExecuteCommand(command, 5000);

        command = " copy \"" + filePath + "\"  \"" + directory + filenameToSave + "\"";

        ExecuteCommand(command, 5000);


        command = "NET USE " + directory + " /delete";
        ExecuteCommand(command, 5000);
    }

Ayrıca ExecuteCommand işlevi:

public static int ExecuteCommand(string command, int timeout)
    {
        var processInfo = new ProcessStartInfo("cmd.exe", "/C " + command)
                              {
                                  CreateNoWindow = true, 
                                  UseShellExecute = false, 
                                  WorkingDirectory = "C:\\",
                              };

        var process = Process.Start(processInfo);
        process.WaitForExit(timeout);
        var exitCode = process.ExitCode;
        process.Close();
        return exitCode;
    } 

Bu işlevler benim için çok hızlı ve kararlı çalıştı.


1
Paylaşım eşlemesi başarısız olursa, dönüş kodları ne olurdu?
surega

14

Luke Quinane çözümü iyi görünüyor, ancak ASP.NET MVC uygulamamda yalnızca kısmen çalıştı. Aynı sunucuda farklı kimlik bilgilerine sahip iki paylaşıma sahip olmak, kimliğe bürünme özelliğini yalnızca ilki için kullanabilirsiniz.

WNetAddConnection2 ile ilgili sorun ayrıca farklı Windows sürümlerinde farklı davranmasıdır. Bu yüzden alternatifler aradım ve LogonUser işlevini buldum . ASP.NET de çalışan benim kod İşte:

public sealed class WrappedImpersonationContext
{
    public enum LogonType : int
    {
        Interactive = 2,
        Network = 3,
        Batch = 4,
        Service = 5,
        Unlock = 7,
        NetworkClearText = 8,
        NewCredentials = 9
    }

    public enum LogonProvider : int
    {
        Default = 0,  // LOGON32_PROVIDER_DEFAULT
        WinNT35 = 1,
        WinNT40 = 2,  // Use the NTLM logon provider.
        WinNT50 = 3   // Use the negotiate logon provider.
    }

    [DllImport("advapi32.dll", EntryPoint = "LogonUserW", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool LogonUser(String lpszUsername, String lpszDomain,
        String lpszPassword, LogonType dwLogonType, LogonProvider dwLogonProvider, ref IntPtr phToken);

    [DllImport("kernel32.dll")]
    public extern static bool CloseHandle(IntPtr handle);

    private string _domain, _password, _username;
    private IntPtr _token;
    private WindowsImpersonationContext _context;

    private bool IsInContext
    {
        get { return _context != null; }
    }

    public WrappedImpersonationContext(string domain, string username, string password)
    {
        _domain = String.IsNullOrEmpty(domain) ? "." : domain;
        _username = username;
        _password = password;
    }

    // Changes the Windows identity of this thread. Make sure to always call Leave() at the end.
    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    public void Enter()
    {
        if (IsInContext)
            return;

        _token = IntPtr.Zero;
        bool logonSuccessfull = LogonUser(_username, _domain, _password, LogonType.NewCredentials, LogonProvider.WinNT50, ref _token);
        if (!logonSuccessfull)
        {
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }
        WindowsIdentity identity = new WindowsIdentity(_token);
        _context = identity.Impersonate();

        Debug.WriteLine(WindowsIdentity.GetCurrent().Name);
    }

    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    public void Leave()
    {
        if (!IsInContext)
            return;

        _context.Undo();

        if (_token != IntPtr.Zero)
        {
            CloseHandle(_token);
        }
        _context = null;
    }
}

Kullanımı:

var impersonationContext = new WrappedImpersonationContext(Domain, Username, Password);
impersonationContext.Enter();

//do your stuff here

impersonationContext.Leave();

2
Bu yaklaşım benim için iyi çalıştı, ancak testlerimde bir etki alanı kullanıcı hesabıyla kötü bir parola kullanıldığında, kullanıcının hemen kilitli duruma geçtiğini fark ettim. alan adı politikamız bundan önce 3 başarısız giriş denemesi gerektirir, ancak bu yaklaşımla kötü bir deneme yapılır ve kilitlenirsiniz. Yani, dikkatli kullanın ...
Kellyb

5

VB. için Luke Quinane kodunun VB.NET eşdeğerini seviyor (teşekkürler Luke!)

Imports System
Imports System.Net
Imports System.Runtime.InteropServices
Imports System.ComponentModel

Public Class NetworkConnection
    Implements IDisposable

    Private _networkName As String

    Public Sub New(networkName As String, credentials As NetworkCredential)
        _networkName = networkName

        Dim netResource = New NetResource() With {
             .Scope = ResourceScope.GlobalNetwork,
             .ResourceType = ResourceType.Disk,
             .DisplayType = ResourceDisplaytype.Share,
             .RemoteName = networkName
        }

        Dim userName = If(String.IsNullOrEmpty(credentials.Domain), credentials.UserName, String.Format("{0}\{1}", credentials.Domain, credentials.UserName))

        Dim result = WNetAddConnection2(NetResource, credentials.Password, userName, 0)

        If result <> 0 Then
            Throw New Win32Exception(result, "Error connecting to remote share")
        End If
    End Sub

    Protected Overrides Sub Finalize()
        Try
            Dispose (False)
        Finally
            MyBase.Finalize()
        End Try
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose (True)
        GC.SuppressFinalize (Me)
    End Sub

    Protected Overridable Sub Dispose(disposing As Boolean)
        WNetCancelConnection2(_networkName, 0, True)
    End Sub

    <DllImport("mpr.dll")> _
    Private Shared Function WNetAddConnection2(netResource As NetResource, password As String, username As String, flags As Integer) As Integer
    End Function

    <DllImport("mpr.dll")> _
    Private Shared Function WNetCancelConnection2(name As String, flags As Integer, force As Boolean) As Integer
    End Function

End Class

<StructLayout(LayoutKind.Sequential)> _
Public Class NetResource
    Public Scope As ResourceScope
    Public ResourceType As ResourceType
    Public DisplayType As ResourceDisplaytype
    Public Usage As Integer
    Public LocalName As String
    Public RemoteName As String
    Public Comment As String
    Public Provider As String
End Class

Public Enum ResourceScope As Integer
    Connected = 1
    GlobalNetwork
    Remembered
    Recent
    Context
End Enum

Public Enum ResourceType As Integer
    Any = 0
    Disk = 1
    Print = 2
    Reserved = 8
End Enum

Public Enum ResourceDisplaytype As Integer
    Generic = &H0
    Domain = &H1
    Server = &H2
    Share = &H3
    File = &H4
    Group = &H5
    Network = &H6
    Root = &H7
    Shareadmin = &H8
    Directory = &H9
    Tree = &HA
    Ndscontainer = &HB
End Enum

3

Kudreti çalışma kullandığını Seçeneklerden biri WindowsIdentity.Impersonate, istenen bir kullanıcı haline (iplik anapara ve değiştirme) şöyle . Korkarım p / invoke'a geri dönüyorum ...

Başka arsız (ve eşit ideal olmaktan uzak) seçeneği işi yapmak için bir işlem spawn olabilir ... ProcessStartInfokabul eden bir .UserName, .Passwordve.Domain .

Son olarak - hizmeti erişimi olan özel bir hesapta çalıştırıyor olabilirsiniz? (bunun bir seçenek olmadığını açıkladığınız için kaldırıldı).


süreç olayının çok kötü bir fikir olduğunu düşünmüyorum. google, kromda çok işlemciliğin yararları hakkında bazı teknik incelemeler yayınladı.
Dustin Getz

İş parçacığı yöneticisini yerel makinede hesabı olmayan bir kullanıcı olarak değiştirmek mümkün müdür?
gyrolf

Dürüst olmak gerekirse, bilmiyorum ... Öğrenmek için LogonUser'ı farklı bir alan adıyla denemeniz gerekir.
Marc Gravell

3

Tamam ... ben de rezondurabilirim ..

Yasal Uyarı: Ben sadece 18+ saat (tekrar) bir gün vardı .. Ben yaşlı ve unutkan .. Yazamam .. Kısa bir dikkat süresi var bu yüzden hızlı cevap daha iyi .. :-)

Soru:

İş parçacığı yöneticisini yerel makinede hesabı olmayan bir kullanıcı olarak değiştirmek mümkün müdür?

Cevap:

Evet, kullandığınız kimlik bilgileri yerel olarak tanımlanmamış ya da "orman" dışında olsa bile bir iş parçacığı ilkesini değiştirebilirsiniz.

Ben sadece bir hizmetten NTLM kimlik doğrulaması ile bir SQL sunucusuna bağlanmaya çalışırken bu sorunla karşılaştı. Bu çağrı, kimliğe bürünmeden önce kimlik doğrulaması yapmak için yerel bir hesaba veya bir etki alanı hesabına ihtiyacınız olduğu anlamına gelen işlemle ilişkili kimlik bilgilerini kullanır. Filan, filan ...

Fakat...

???? _ NEW_CREDENTIALS özniteliğiyle LogonUser (..) çağrıldığında, kimlik bilgilerini doğrulamaya çalışmadan bir güvenlik belirteci döndürülür. Kewl .. Hesabı "orman" içinde tanımlamak zorunda değilsiniz. Jetonu aldıktan sonra, yeni bir jetonla sonuçlanan kimliğe bürünme özelliğini etkinleştirme seçeneğiyle DuplicateToken () öğesini çağırmanız gerekebilir. Şimdi SetThreadToken (NULL, token) çağırın; (& Jeton olabilir?) .. ImpersonateLoggedonUser (jeton) çağrısı; gerekebilir, ama sanmıyorum. Yukarı bak ..

Yapman gerekeni yap ..

ImpersonateLoggedonUser () öğesini çağırdıysanız RevertToSelf () öğesini çağırın, ardından SetThreadToken (NULL, NULL); (Sanırım ... bak) ve sonra oluşturulan tutamaçlarda CloseHandle () ..

Hiçbir söz ama bu benim için çalıştı ... Bu (saçlarım gibi) başımın üst kapalı ve büyü olamaz !!!



1

Ayrıca FAKE ile kullanmak için F # ' a taşındı

module NetworkShare

open System
open System.ComponentModel
open System.IO
open System.Net
open System.Runtime.InteropServices

type ResourceScope =
| Connected = 1
| GlobalNetwork = 2
| Remembered = 3
| Recent = 4
type ResourceType =
| Any = 0
| Disk = 1
| Print = 2
| Reserved = 8
type ResourceDisplayType =
| Generic = 0x0
| Domain = 0x01
| Server = 0x02
| Share = 0x03
| File = 0x04
| Group = 0x05
| Network = 0x06
| Root = 0x07
| Shareadmin = 0x08
| Directory = 0x09
| Tree = 0x0a
| Ndscontainer = 0x0b

//Uses of this construct may result in the generation of unverifiable .NET IL code.
#nowarn "9"
[<StructLayout(LayoutKind.Sequential)>]
type NetResource =
  struct
    val mutable Scope : ResourceScope
    val mutable ResourceType : ResourceType
    val mutable DisplayType : ResourceDisplayType
    val mutable Usage : int
    val mutable LocalName : string
    val mutable RemoteName : string
    val mutable Comment : string
    val mutable Provider : string
    new(name) = {
      // lets preset needed fields
      NetResource.Scope = ResourceScope.GlobalNetwork
      ResourceType = ResourceType.Disk
      DisplayType = ResourceDisplayType.Share
      Usage = 0
      LocalName = null
      RemoteName = name
      Comment = null
      Provider = null
    }
  end

type WNetConnection(networkName : string, credential : NetworkCredential) =
  [<Literal>]
  static let Mpr = "mpr.dll"
  [<DllImport(Mpr, EntryPoint = "WNetAddConnection2")>]
  static extern int connect(NetResource netResource, string password, string username, int flags)
  [<DllImport(Mpr, EntryPoint = "WNetCancelConnection2")>]
  static extern int disconnect(string name, int flags, bool force)

  let mutable disposed = false;

  do
    let userName = if String.IsNullOrWhiteSpace credential.Domain
                   then credential.UserName
                   else credential.Domain + "\\" + credential.UserName
    let resource = new NetResource(networkName)

    let result = connect(resource, credential.Password, userName, 0)

    if result <> 0 then
      let msg = "Error connecting to remote share " + networkName
      new Win32Exception(result, msg)
      |> raise

  let cleanup(disposing:bool) =
    if not disposed then
      disposed <- true
      if disposing then () // TODO dispose managed resources here
      disconnect(networkName, 0, true) |> ignore

  interface IDisposable with
    member __.Dispose() =
      disconnect(networkName, 0, true) |> ignore
      GC.SuppressFinalize(__)

  override __.Finalize() = cleanup(false)

type CopyPath =
  | RemotePath of string * NetworkCredential
  | LocalPath of string

let createDisposable() =
  {
    new IDisposable with
      member __.Dispose() = ()
  }

let copyFile overwrite destPath srcPath : unit =
  use _srcConn =
    match srcPath with
    | RemotePath(path, credential) -> new WNetConnection(path, credential) :> IDisposable
    | LocalPath(_) -> createDisposable()
  use _destConn =
    match destPath with
    | RemotePath(path, credential) -> new WNetConnection(path, credential) :> IDisposable
    | LocalPath(_) -> createDisposable()
  match srcPath, destPath with
  | RemotePath(src, _), RemotePath(dest, _)
  | LocalPath(src), RemotePath(dest, _)
  | RemotePath(src, _), LocalPath(dest)
  | LocalPath(src), LocalPath(dest) ->
    if FileInfo(src).Exists |> not then
      failwith ("Source file not found: " + src)
    let destFilePath =
      if DirectoryInfo(dest).Exists then Path.Combine(dest, Path.GetFileName src)
      else dest
    File.Copy(src, destFilePath, overwrite)

let rec copyDir copySubDirs filePattern destPath srcPath =
  use _srcConn =
    match srcPath with
    | RemotePath(path, credential) -> new WNetConnection(path, credential) :> IDisposable
    | LocalPath(_) -> createDisposable()
  use _destConn =
    match destPath with
    | RemotePath(path, credential) -> new WNetConnection(path, credential) :> IDisposable
    | LocalPath(_) -> createDisposable()
  match srcPath, destPath with
  | RemotePath(src, _), RemotePath(dest, _)
  | LocalPath(src), RemotePath(dest, _)
  | RemotePath(src, _), LocalPath(dest)
  | LocalPath(src), LocalPath(dest) ->
    let dir = DirectoryInfo(src)
    if dir.Exists |> not then
      failwith ("Source directory not found: " + src)

    let dirs = dir.GetDirectories()
    if Directory.Exists(dest) |> not then
      Directory.CreateDirectory(dest) |> ignore

    let files = dir.GetFiles(filePattern)
    for file in files do
      let tempPath = Path.Combine(dest, file.Name)
      file.CopyTo(tempPath, false) |> ignore

    if copySubDirs then
      for subdir in dirs do
        let subdirSrc =
          match srcPath with
          | RemotePath(_, credential) -> RemotePath(Path.Combine(dest, subdir.Name), credential)
          | LocalPath(_) -> LocalPath(Path.Combine(dest, subdir.Name))
        let subdirDest =
          match destPath with
          | RemotePath(_, credential) -> RemotePath(subdir.FullName, credential)
          | LocalPath(_) -> LocalPath(subdir.FullName)
        copyDir copySubDirs filePattern subdirDest subdirSrc

0

Bunun gibi bir şey eklemeye bakmalısınız:

<identity impersonate="true" userName="domain\user" password="****" />

Web.config dosyasına.

Daha fazla bilgi.


Bazı Kurumsal Güvenlik, uygulamayı kullanarak uygulamayı izleyemedikleri ve aynı veya güvenilir etki alanında olması gerektiği için kimliğe bürünme kullanımını engeller. Bence kimliğe bürünmüş destek tespit edildi. Pinvoke içeren bir etki alanı hizmeti hesabı, gitmenin yolu gibi görünüyor.
Jim
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.