项目中的文件需要保存到网络存储设备中,之前用的是NAS。因没来得及采购就先用Samba顶上。代码发现通用……
一、定义:
Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成。SMB(Server Messages Block,信息服务块)是一种在局域网上共享文件和打印机的一种通信协议,它为局域网内的不同计算机之间提供文件及打印机等资源的共享服务。SMB协议是客户机/服务器型协议,客户机通过该协议可以访问服务器上的共享文件系统、打印机及其他资源。通过设置“NetBIOS over TCP/IP”使得Samba不但能与局域网络主机分享资源,还能与全世界的电脑分享资源。(百科)
NAS(Network Attached Storage)网络存储基于标准网络协议实现数据传输,为网络中的Windows / Linux / Mac OS 等各种不同操作系统的计算机提供文件共享和数据备份。(百科)
二、二者有什么区别
1、Samba是一个软件,NAS是一个存储解决方案
2、FTP基于windows平台的,Samba是基于linux平台的,NAS是基于存储平台的(硬件)
三、主要代码LogonImpersonateHelper类用于IIS更换运行用户、WNetHelper类用于创建网络映射
public class LogonImpersonateHelper : IDisposable { static public string DefaultDomain { get { return "."; } } const int LOGON32_LOGON_INTERACTIVE = 2; const int LOGON32_PROVIDER_DEFAULT = 0; [System.Runtime.InteropServices.DllImport("Kernel32.dll")] extern static int FormatMessage(int flag, ref IntPtr source, int msgid, int langid, ref string buf, int size, ref IntPtr args); [System.Runtime.InteropServices.DllImport("Kernel32.dll")] extern static bool CloseHandle(IntPtr handle); [System.Runtime.InteropServices.DllImport("Advapi32.dll", SetLastError = true)] extern static bool LogonUser( string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken ); IntPtr token; System.Security.Principal.WindowsImpersonationContext context; public LogonImpersonateHelper(string username, string password) { if (username.IndexOf("//") == -1) { Init(username, password, DefaultDomain); } else { string[] pair = username.Split(new char[] { '/' }, 2);//username.Split(new char[] { '//' }, 2); Init(pair[1], password, pair[0]); } } public LogonImpersonateHelper(string username, string password, string domain) { Init(username, password, domain); } void Init(string username, string password, string domain) { if (LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token)) { bool error = true; try { context = System.Security.Principal.WindowsIdentity.Impersonate(token); error = false; } finally { if (error) CloseHandle(token); } } else { int err = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); IntPtr tempptr = IntPtr.Zero; string msg = null; FormatMessage(0x1300, ref tempptr, err, 0, ref msg, 255, ref tempptr); throw (new Exception(msg)); } } ~LogonImpersonateHelper() { Dispose(); } public void Dispose() { if (context != null) { try { context.Undo(); } finally { CloseHandle(token); context = null; } } } }
/// <summary> /// 网络驱动器 映射帮助类 /// </summary> public class WNetHelper { [DllImport("mpr.dll", EntryPoint = "WNetAddConnection2")] private static extern uint WNetAddConnection2(NetResource lpNetResource, string lpPassword, string lpUsername, uint dwFlags); [DllImport("Mpr.dll", EntryPoint = "WNetCancelConnection2")] private static extern uint WNetCancelConnection2(string lpName, uint dwFlags, bool fForce); [StructLayout(LayoutKind.Sequential)] public class NetResource { public int dwScope; public int dwType; public int dwDisplayType; public int dwUsage; public string lpLocalName; public string lpRemoteName; public string lpComment; public string lpProvider; } /// <summary> /// 为网络共享做本地映射 /// </summary> /// <param name="username">访问用户名(windows系统需要加计算机名,如:comp-1/user-1)</param> /// <param name="password">访问用户密码</param> /// <param name="remoteName">网络共享路径(如://192.168.0.9/share)</param> /// <param name="localName">本地映射盘符</param> /// <returns></returns> public static uint WNetAddConnection(string username, string password, string remoteName, string localName) { NetResource netResource = new NetResource(); netResource.dwScope = 2; netResource.dwType = 1; netResource.dwDisplayType = 3; netResource.dwUsage = 1; netResource.lpLocalName = localName; netResource.lpRemoteName = remoteName.TrimEnd('\'); uint result = WNetAddConnection2(netResource, password, username, 0); return result; } public static uint WNetCancelConnection(string name, uint flags, bool force) { uint nret = WNetCancelConnection2(name, flags, force); return nret; } }
创建文件夹
/// <summary> /// Samba创建文件夹 /// </summary> /// <param name="path"></param> /// <returns></returns> public static bool CreateDirectory(string path) { uint state = 0; if (!Directory.Exists("Z:")) { string nasPath = ConfigHelper.NasPath; string root = Directory.GetDirectoryRoot(nasPath); state = WNetHelper.WNetAddConnection(ConfigHelper.NasAccount, ConfigHelper.NasPassword, ConfigHelper.NasPath, root.Replace("/", "").Replace("\", "")); } if (state.Equals(0)) { Directory.CreateDirectory(path); return true; } else { throw new Exception("添加网络驱动器错误,错误号:" + state.ToString()); } }
四、如何使用
//在访问映射磁盘之前首先调用此类为IIS更换运行用户 LogonImpersonateHelper imper = new LogonImpersonateHelper("qewd", "1,23#$&@qw"); //创建网络映射 WNetHelper.WNetAddConnection(ConfigHelper.NasAccount, ConfigHelper.NasPassword, ConfigHelper.NasPath, root.Replace("/", "").Replace("\", ""));
五、问题来了
在本地怎么跑怎么成功,放到服务器上就来问题了。环境:windows server2008、IIS7 报错:“未知的用户名或错误密码。”
折腾了半天,折腾的事情就不说了,做个笔记
解决方案:
1、IIS 7 标示改了最高权限(暂无 办法先这样解决)
2、把Samba账号、密码添加到计算机本地用户组中
六、结果-成功