zoukankan      html  css  js  c++  java
  • C# 代码实现设置用户"NETWORK SERVICE"具有对文件夹的读取权限。

    设置用户"NETWORK SERVICE"具有对文件夹的读取权限。

    原帖地址: http://www.cnblogs.com/sjhrun2001/archive/2009/03/18/1415804.html

    复制代码
    1 System.Security.AccessControl.DirectorySecurity fSec;

    3 string path = "D:\Test";
    4 fSec = new DirectorySecurity();
    5 //设置权限的应用为文件夹本身、子文件夹及文件
    6 //所以需要InheritanceFlags.ContainerInherit 或 InheritanceFlags.ObjectInherit
    7 fSec.AddAccessRule(new FileSystemAccessRule("NETWORK SERVICE", FileSystemRights.Read, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
    8 System.IO.Directory.SetAccessControl(path, fSec);
    9
    复制代码

    顺便提一下,NETWORK SERVICE是IIS6.0的默认用户,而ASPNET是IIS5.0的默认用户。
    有一个问题:NETWORK SERVICE在Window2003的电脑管理/用户里面并没有这个用户。

    ---------------------------------------

    原文:

    http://www.cnblogs.com/leosky2008/archive/2007/08/08/847405.html

    在文件操作中,常常会遇到 对所访问的文件夹没有权限 的错误,下面介绍C#中怎么设置文件夹的权限:
      
    1/// <summary>
    2        /// 为创建的临时文件分配权限
    3        /// </summary>
    4        /// <param name="pathname"></param>
    5        /// <param name="username"></param>
    6        /// <param name="power"></param>
    7        /// <remarks>SKY 2007-8-6</remarks>
    8        public void addpathPower(string pathname, string username, string power)
    9        {
    10
    11            DirectoryInfo dirinfo = new DirectoryInfo(pathname);
    12
    13            if ((dirinfo.Attributes & FileAttributes.ReadOnly) != 0)
    14            {
    15                dirinfo.Attributes = FileAttributes.Normal;
    16            }
    17
    18            //取得访问控制列表
    19            DirectorySecurity dirsecurity = dirinfo.GetAccessControl();
    20
    21            switch (power)
    22            {
    23                case "FullControl":
    24                    dirsecurity.AddAccessRule(new FileSystemAccessRule(username, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));
    25                    break;
    26                case "ReadOnly":
    27                    dirsecurity.AddAccessRule(new FileSystemAccessRule(username, FileSystemRights.Read, AccessControlType.Allow));
    28                    break;
    29                case "Write":
    30                    dirsecurity.AddAccessRule(new FileSystemAccessRule(username, FileSystemRights.Write, AccessControlType.Allow));
    31                    break;
    32                case "Modify":
    33                    dirsecurity.AddAccessRule(new FileSystemAccessRule(username, FileSystemRights.Modify, AccessControlType.Allow));
    34                    break;
    35            }
    36        }

    DirectoryInfo是需要实例化的,而且实例化的时候必须指定文件夹路径,Directory则是静态类.

    主程序中调用的写法:

    1private void CreateDirectory()
    2{
    3   
    4   addpathPower(sPath, "ASPNET", "FullControl");
    5   
    6}
       一般来说 
    Username 选用 ASPNET


    ------------------------------------
     这几天由于工作需要,需要用C#开发一个设置文件夹共享,并为共享的文件夹设置共享权限的功能。在开发过程中发现了一些有趣的问题,
    就是如果用程序的方式创建一个共享目录,那么就是无法直接用程序的方式设置它的共享权限。更为奇怪的是如果手动去改下下共享权限 (改前和改后的设置都一样),
    就可以以程序的方式设置 共享权限了。
      这里我贴出创建共享目录的代码
    /// <summary>
            /// 共享目录
            /// </summary>
            /// <param name="folderPath">目录地址</param>
            /// <param name="shareName">共享名称</param>
            /// <param name="description">描述</param>
            /// <param name="tempShareName">临时共享目录</param>
            /// <param name="returnMsg">返回消息</param>
            /// <returns></returns> 
    public static bool ShareFolder(string folderPath, string shareName, string description, out string returnMsg)
            {
                bool bRet = false;
                try
                {
                    returnMsg = "";
                    if (Directory.Exists(folderPath))
                    {
                        ManagementBaseObject oSecurityDescriptor = GetSecurityDescriptorFromBinary(user);
                        ManagementClass oManagementClass = new ManagementClass("Win32_Share");
                        ManagementBaseObject oInParams = oManagementClass.GetMethodParameters("Create");
                        ManagementBaseObject oOutParams = null;
                        oInParams["Description"] = description;
                        oInParams["Name"] = shareName;
                        oInParams["Path"] = folderPath;
                        oInParams["Type"] = DISK_DRIVE;
                        oInParams["Access"] = null; //默认的共享权限是Everyone
            /*
    如果oInParams["Access"] 不设置或者设置为null,你就会奇怪的发现,当你先要用程序再去设置共享权限时就不行了(xp和2003下,win7,win2008缺可以)
    */ 
                        oOutParams = oManagementClass.InvokeMethod("Create", oInParams, null);
                        if ((uint)(oOutParams.Properties["ReturnValue"].Value) != 0)
                        {
                            returnMsg = string.Format("无法共享目录[{0}]!", folderPath);
                        }
                        else
                        {
                            bRet = true;
                        }
                    }
                    else
                    {
                        returnMsg = string.Format("不存在目录[{0}]!", folderPath);
                    }
                }
                catch (Exception ex)
                {
                    returnMsg = ex.Message;
                }
                return bRet;
            }
    设置权限的普通方法:
    /// <summary>
            /// 设置共享目录的共享权限
            /// </summary>
            /// <param name="folderPath">共享目录名</param>
            /// <param name="user">共享权限用户</param>
            /// <param name="returnMsg">返回消息</param>
            /// <returns></returns>
            public static bool SetPermission(string shareName, string user, out string returnMsg)
            {
                bool bRet = false;
                returnMsg = "";
                //判断用户是否存在
                if (!IsUserExists(user))
                {
                    returnMsg = string.Format("用于[{0}]不存在", user);
                    return bRet;
                }
                // Step 1 - Getting the user Account Object
                string sShareName =shareName;
                ManagementObject oShareSecuritySetting=  null;
                ManagementObjectSearcher oSearcher = new ManagementObjectSearcher("Select * from Win32_LogicalShareSecuritySetting where     Name = '" + sharedName + "'");
                //ManagementObjectSearcher oSearcher = new ManagementObjectSearcher("Select * from Win32_LogicalShareSecuritySetting");
                ManagementObjectCollection oResultOfSearch = oSearcher.Get();
                if (oResultOfSearch.Count > 0)
                {
                    //The search might return a number of objects with same shared name. I assume there is just going to be one
                    foreach (ManagementObject sharedFolder in oResultOfSearch)
                    {                   
                oShareSecuritySetting= sharedFolder;
                        break;
                    }
                }
                if (oShareSecuritySetting!= null)
                {
                    ManagementBaseObject oSecurityDescriptorObject = oShareSecuritySetting.InvokeMethod("GetSecurityDescriptor", null, null);
                    if (oSecurityDescriptorObject != null)
                    {
                        if ((uint)(oSecurityDescriptorObject.Properties["ReturnValue"].Value) == 0)
                        {
                            ManagementBaseObject oSecurityDescriptor = oSecurityDescriptorObject.Properties["Descriptor"].Value as ManagementBaseObject;
                            // Step 2 --  Access Control List from the security descriptor
                            int iExistingAcessControlEntriesCount = 0;
                            ManagementBaseObject[] oAccessControlList = oSecurityDescriptor.Properties["DACL"].Value as ManagementBaseObject[];
                            if (oAccessControlList != null)
                            {
                                // Otherwise, resize the list to allow for all new users.
                                iExistingAcessControlEntriesCount = oAccessControlList.Length;
                                Array.Resize(ref oAccessControlList, oAccessControlList.Length + 1);
                            }
                            else
                            {
                                // If there aren't any entries in access control list or the list is empty - create one
                                oAccessControlList = new ManagementBaseObject[1];
                            }
                            // Step 3 - Getting the user Account Object
                            string sUserDomain = Environment.UserDomainName;
                            ManagementObject oUserAccountObject = GetUserAccountObject(sUserDomain, user);
                            ManagementObject oSecurityIdentfierObject = new ManagementObject(string.Format("Win32_SID.SID='{0}'", (string)oUserAccountObject.Properties["SID"].Value));
                            oSecurityIdentfierObject.Get();
                            // Step 4 - Create Trustee Object
                            ManagementObject oTrusteeObject = CreateTrustee(sUserDomain, user, oSecurityIdentfierObject);
                            // Step 5 - Create Access Control Entry
                            ManagementObject oAccessControlEntry = CreateAccessControlEntry(oTrusteeObject, false);
                            // Step 6 - Add Access Control Entry to the Access Control List
                            oAccessControlList[iExistingAcessControlEntriesCount] = oAccessControlEntry;
                            // Step 7 - Assign access Control list to security desciptor
                            oSecurityDescriptor.Properties["DACL"].Value = oAccessControlList;
                            // Step 8 - Assign access Control list to security desciptor
                            ManagementBaseObject oParameterForSetSecurityDescriptor = oSharedFolder.GetMethodParameters("SetSecurityDescriptor");
                            oParameterForSetSecurityDescriptor["Descriptor"] = oSecurityDescriptor;
                            oShareSecuritySetting.InvokeMethod("SetSecurityDescriptor", oParameterForSetSecurityDescriptor, null);
                            bRet = true;
                        }
                        else
                        {
                            returnMsg = string.Format("共享目录[{0}]的安全描述符(SecurityDescriptorObject)的返回值错误!", sShareName);
                        }
                    }
                    else
                    {
                        returnMsg = string.Format("无法获取共享目录[{0}]的安全描述符(SecurityDescriptorObject)", sShareName);
                    }
                }
                else
                {
                    returnMsg = string.Format("无法获取共享目录[{0}]的共享安全设置!", sShareName);
                }
                return bRet;
            }
        /// <summary>
            /// 获取账户对象
            /// </summary>
            /// <param name="domain">用户的域名</param>
            /// <param name="alias">用户名称别名</param>
            /// <returns></returns>
            private static ManagementObject GetUserAccountObject(string domain, string alias)
            {
                ManagementObject oUserAccountObject = null;
                ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(string.Format("select * from Win32_Account where Name = '{0}' and Domain='{1}'", alias, domain));
                ManagementObjectCollection oResultOfSearch = oSearcher.Get();
                if (oResultOfSearch.Count > 0)
                {
                    foreach (ManagementObject userAccount in oResultOfSearch)
                    {
                        oUserAccountObject = userAccount;
                        break;
                    }
                }
                return oUserAccountObject;
            }
            /// <summary>
            /// 创建指定用户的信任项
            /// </summary>
            /// <param name="domain">域名</param>
            /// <param name="userName">用户名</param>
            /// <param name="securityIdentifierOfUser">用户的权限标识</param>
            /// <returns></returns>
            private static ManagementObject CreateTrustee(string domain, string userName, ManagementObject securityIdentifierOfUser)
            {
                ManagementObject oTrusteeObject = new ManagementClass("Win32_Trustee").CreateInstance();
                oTrusteeObject.Properties["Domain"].Value = domain;
                oTrusteeObject.Properties["Name"].Value = userName;
                oTrusteeObject.Properties["SID"].Value = securityIdentifierOfUser.Properties["BinaryRepresentation"].Value;
                oTrusteeObject.Properties["SidLength"].Value = securityIdentifierOfUser.Properties["SidLength"].Value;
                oTrusteeObject.Properties["SIDString"].Value = securityIdentifierOfUser.Properties["SID"].Value;
                return oTrusteeObject;
            }
            /// <summary>
            /// 创建指定用户的访问控制项(Access Control Entry)对象
            /// </summary>
            /// <param name="trustee">用户的信任项对象</param>
            /// <param name="deny">用户权限是拒绝还是允许</param>
            /// <returns></returns>
            private static ManagementObject CreateAccessControlEntry(ManagementObject trustee, bool deny)
            {
                ManagementObject oAceObject = new ManagementClass("Win32_ACE").CreateInstance();
                oAceObject.Properties["AccessMask"].Value = 0x1U | 0x2U | 0x4U | 0x8U | 0x10U | 0x20U | 0x40U | 0x80U | 0x100U | 0x10000U | 0x20000U | 0x40000U | 0x80000U | 0x100000U; // all permissions
                oAceObject.Properties["AceFlags"].Value = 0x0U; // no flags
                oAceObject.Properties["AceType"].Value = deny ? 1U : 0U; // 0 = allow, 1 = deny
                oAceObject.Properties["Trustee"].Value = trustee;
                return oAceObject;
            }
            /// <summary>
            /// 检查用户是否存在
            /// </summary>
            /// <param name="user"></param>
            /// <param name="returnMsg"></param>
            /// <returns></returns>
            public static bool IsUserExists(string userName)
            {
                bool bRet = false;
                DirectoryEntry oLocalMachine = null;
                DirectoryEntry oNewUser = null;
                try
                {
                    oLocalMachine = new DirectoryEntry("WinNT://" + Environment.MachineName);
                    oNewUser = oLocalMachine.Children.Find(userName, "user");
                    bRet = true;
                }
                catch
                {
                    bRet = false;
                }
                return bRet;
            }
    运行代码上面这段代码时你会发现
    ManagementObject oShareSecuritySetting=  null;
                ManagementObjectSearcher oSearcher = new ManagementObjectSearcher("Select * from Win32_LogicalShareSecuritySetting where Name = '" + sharedName + "'");
                ManagementObjectCollection oResultOfSearch = oSearcher.Get();
                if (oResultOfSearch.Count > 0)
                {
                    //The search might return a number of objects with same shared name. I assume there is just going to be one
                    foreach (ManagementObject sharedFolder in oResultOfSearch)
                    {                   
                oShareSecuritySetting= sharedFolder;
                        break;
                    }
                }
    这句代码片段是无法找到有效的oShareSecuritySetting。但是实际情况是文件夹是共享的而且有一个默认的Everyone的共享权限。这是为啥我找了很久也没答案。
    鉴于无法获取oShareSecuritySetting这个“Win32_LogicalShareSecuritySetting”对象,下一步的权限设置也没法做了。
    其实获取这个对象的最终目的是为了获取下面这个对象 
    ManagementBaseObject oSecurityDescriptor = oSecurityDescriptorObject.Properties["Descriptor"].Value as ManagementBaseObject;
    这就头疼了,这些功能代码的目的就是为了使用程序去设置共享及共享权限,如果需要手动去设置下权限那不是有点隔靴搔痒了。
    最后实在没办了,我只能想了个笨办法。既然手动创建的共享目录能够获取oSecurityDescriptor 这个对象,那能不能我把这个对象保存下来能,应为只要有了
    oSecurityDescriptor这个对象,就可以在这个对象了设置我们自己想要的用户权限了,设置方法上面的代码中有例子的。
    最后想出来办法是用.net的序列化方法去序列化一个实现获取到的oSecurityDescriptor对象,把这个对象保存在一个文件里,下次在进行反序列化获取这个对象。
    需要注意一点的是。无法获取oShareSecuritySetting只会发生在第一次创建共享目录的时候(注意:使用代码创建的),如果第一次为这个共享目录设置了共享权限,那么下次次再设置权限就没有障碍了。烦啊。。。
    好了,还是说序列化吧,如下代码:
    private static void ObjectSerialize(object serObj)
            {
                using (FileStream oFileStream = new FileStream(@"C:LogicalShareSecuritySetting.dat", FileMode.Create))
                {
                    BinaryFormatter oFormatter = new BinaryFormatter();
                    oFormatter.Serialize(oFileStream, serObj);
                }
            }
    ObjectSerialize(oSecurityDescriptor);
    这样就把这个对象永久保存在C:LogicalShareSecuritySetting.dat这个文件里了,为了部署方便,我们可以把这个文件作为一个嵌入的资源嵌入在我们的程序中,下次我们就可以这样反序列化这个对象了:
    private const string LOGICAL_SHARESECURITY_SETTING=“Namespace.LogicalShareSecuritySetting.dat”; 
    ManagementBaseObject oSecurityDescriptor= null;
                try
                {
                    Assembly oAsm = Assembly.GetExecutingAssembly();
                    using (Stream oStream = oAsm.GetManifestResourceStream(LOGICAL_SHARESECURITY_SETTING))
                    {
                        BinaryFormatter oFormatter = new BinaryFormatter();                    
            oSecurityDescriptor= oFormatter.Deserialize(oStream) as ManagementBaseObject;
                    }
                }
                catch
                { }
    一旦反序列化成功这个oSecurityDescriptor,我们就可以为这个对象赋值一个我们想要的用户权限啦,如下:
    if (oSecurityDescriptor != null)
    {
        ManagementBaseObject[] oAccessControlList = null;
        oAccessControlList = new ManagementBaseObject[1];
        // Step 3 - Getting the user Account Object
        string sUserDomain = Environment.UserDomainName;
        ManagementObject oUserAccountObject = GetUserAccountObject(sUserDomain, user);  //这个user就是本地计算机的用户名,如Guest等。
        ManagementObject oSecurityIdentfierObject = new ManagementObject(string.Format("Win32_SID.SID='{0}'", (string)oUserAccountObject.Properties["SID"].Value));
        oSecurityIdentfierObject.Get();
        // Step 4 - Create Trustee Object
        ManagementObject oTrusteeObject = CreateTrustee(sUserDomain, user, oSecurityIdentfierObject);
        // Step 5 - Create Access Control Entry
        ManagementObject oAccessControlEntry = CreateAccessControlEntry(oTrusteeObject, false);
        // Step 6 - Add Access Control Entry to the Access Control List
        oAccessControlList[0] = oAccessControlEntry;
        // Step 7 - Assign access Control list to security desciptor    
      oSecurityDescriptor.Properties["DACL"].Value = oAccessControlList;
    }
    一旦设置成功了,那么我们返回第一段设置共享目录代码的地方,记得不记得这段代码
    oInParams["Access"] = null; //默认的共享权限是Everyone
    我们就可以吧获取的 
    oSecurityDescriptor设置给 oInParams["Access"] = oSecurityDescriptor了。
    OK,大家有兴趣试试。如果有什么更好的方法,请一定告诉我哦。我期待有更好的方式解决这个问题。

  • 相关阅读:
    RESTClient使用
    web.xml 的加载过程
    I18N、L10N、G11N
    Oracle游标示例
    MyEclipse转换Eclipse项目无法启动问题(转)
    eclipse默认文件编码
    JAVA为什么要配置环境变量,怎样配置
    TODO Auto-generated method stub
    vc6开发ActiveX并发布全攻略(三)(转)
    高效使用hibernate-validator校验框架
  • 原文地址:https://www.cnblogs.com/amylis_chen/p/8722631.html
Copyright © 2011-2022 走看看