2013-06-10 8 views
0

Я иногда переношу некоторые веб-сайты с одного веб-сервера на другой.сравнить права доступа к файлам Windows (или папке)

После копирования всех файлов со старого сервера на новый сервер мне потребуется некоторое время, чтобы узнать, какие папки или файлы должны быть доступны для записи IIS. (Звучит знакомо, кстати? :))

Я написал приложение WinForms, которое позволяет мне выбрать стартовый каталог. Приложение должно (рекурсивно) сравнивать, если разрешения безопасности каждого файла/каталога равны требованиям безопасности его родительского каталога.

Я хочу использовать это приложение на старом сервере для сканирования каталогов с разными разрешениями.

Пример:C:\MySites\Uploads does not have the same permissions set as its parent directory. (. Эта папка была доступна для записи пользователя IIS «IUSR», в то время как его родительская папка только для чтения)

Приложение почти полное в том смысле, что мне удается пройти все каталоги и файлы. Мне просто нужно сравнить их разрешения!

Не могли бы вы помочь? Вот выдержка из того, где мне нужна ваша помощь.

string results = ""; 

string parentFolderPath = "c:\\someParentDir"; 
string childItemPath = "c:\\someParentDir\\SomeChildDir.ext"; 

DirectorySecurity parentFolderAccessControl = Directory.GetAccessControl(parentFolderPath); 
DirectorySecurity childItemAccessControl = Directory.GetAccessControl(childItemPath); 

if (!parentFolderAccessControl.Equals(childItemAccessControl)) // <-- D'oh here 
{ 
    results += childItemPath + " does not have the same permissions set as its parent directory.\n"; 
} 

The if всегда верно, потому что DirectorySecurities никогда не равны. (Я понимаю, почему это так: ссылка на разные распределения памяти ... бла-бла.) Но какой будет лучший способ сравнить DirectorySecurities?

+0

Я думаю, что этот ответ, вероятно, поможет вам. http://stackoverflow.com/a/1281638/1181408 По сути, вы хотите вызвать GetAccessRules на своих объектах DirectorySecurity, а затем перебрать полученную коллекцию. – cgotberg

+0

@cgotberg Это звучит довольно дорого. Получите обе коллекции. Проверьте, существуют ли пользователи в коллекции1 в коллекции2 и наоборот. И затем для проверки пользователя, если доступ равен. Это была моя отправная точка, но я надеюсь, что у кого-то есть лучшее решение. –

+0

Я полагаю, что это дорого, но в этой концепции изредка приходится мигрировать код, вероятно, это не имеет значения. Вы можете использовать этот общий код .net для сравнения объектов, чтобы сделать глубокое сравнение, и это, вероятно, так дорого, как когда-либо. http://comparenetobjects.codeplex.com/ – cgotberg

ответ

1

Вы не можете использовать Equals(), поскольку этот метод наследуется от Object. Вам нужно найти атрибут идентификации в этом классе DirectorySecurity. Я думаю, String GetSecurityDescriptorSddlForm()

должен выполнять свою работу. Вы можете вызвать Equals() на этом.

Редактировать: Очень жаль, этот метод требует параметра для вызова. Попробуйте найти другой атрибут в DirectorySecurity, который лучше для сравнения.

Редактировать 2: Я не знаком с .NET Security Framework и Right-Management, но что-то вроде этого должно быть вашим подходом. Вы можете сделать! = Resp: == в FileSystemAccessRule.FileSystemRights, потому что этот атрибут является перечислением (внутренне int).

ArrayList notIdenticalList = new ArrayList(); 

     DirectorySecurity parentFolderAccessControl = Directory.GetAccessControl(null); 
     DirectorySecurity childItemAccessControl = Directory.GetAccessControl(null); 
     foreach (FileSystemAccessRule parentRule in parentFolderAccessControl.GetAccessRules(true, true, typeof(NTAccount))) 
     { 
      foreach (FileSystemAccessRule childRule in childItemAccessControl.GetAccessRules(true, true, typeof(NTAccount))) 
      { 
       if (parentRule.FileSystemRights != childRule.FileSystemRights) 
       { 
        // add to not identical-list 
        notIdenticalList.Add(fileToAdd...); 
        break; 
       } 
      } 
     } 
+0

Является ли эта функция чувствительной к тому, в каком порядке перечислены учетные записи пользователей, которые имеют свой специальный доступ? Или он всегда сначала сортируется по учетным записям пользователей? Пример: предположим, что учетная запись System и учетная запись IUSR имеют доступ на запись к каталогу и его родительскому каталогу. Но для первого каталога системная учетная запись указана первыми, а для родительского каталога IUSR указан первым ...? –

+0

Вы имеете в виду Equals() или какую функцию? –

+0

Нет. Я имел в виду функцию, которую вы предложили. Независимо от того, может ли строка быть другой (другой порядок учетной записи пользователя), в то время как эффективные разрешения одинаковы. –

2

Это фактически стало гораздо более сложным, в то время как я работал его, потому что права Окна могут:

  • разделена на Разрешить и Запретить
  • Раздробленность на несколько записей (несколько записей для каждого пользователя в Разрешить/Запретить)

в конце концов, это то, что я сделал из него:

private bool compareAccessControls(
    DirectorySecurity parentAccessControl, 
    DirectorySecurity childAccessControl, 
    out Dictionary<IdentityReference, FileSystemRights> accessAllowRulesGainedByChild, 
    out Dictionary<IdentityReference, FileSystemRights> accessDenyRulesGainedByChild, 
    out Dictionary<IdentityReference, FileSystemRights> accessAllowRulesGainedByParent, 
    out Dictionary<IdentityReference, FileSystemRights> accessDenyRulesGainedByParent 
) 
{ 
    // combine parent access rules 

    Dictionary<IdentityReference, FileSystemRights> combinedParentAccessAllowRules = new Dictionary<IdentityReference, FileSystemRights>(); 
    Dictionary<IdentityReference, FileSystemRights> combinedParentAccessDenyRules = new Dictionary<IdentityReference, FileSystemRights>(); 
    foreach (FileSystemAccessRule parentAccessRule in parentAccessControl.GetAccessRules(true, true, typeof(NTAccount))) 
    { 
     if (parentAccessRule.AccessControlType == AccessControlType.Allow) 
      if (combinedParentAccessAllowRules.ContainsKey(parentAccessRule.IdentityReference)) 
       combinedParentAccessAllowRules[parentAccessRule.IdentityReference] = combinedParentAccessAllowRules[parentAccessRule.IdentityReference] | parentAccessRule.FileSystemRights; 
      else 
       combinedParentAccessAllowRules.Add(parentAccessRule.IdentityReference, parentAccessRule.FileSystemRights); 
     else 
      if (combinedParentAccessDenyRules.ContainsKey(parentAccessRule.IdentityReference)) 
       combinedParentAccessDenyRules[parentAccessRule.IdentityReference] = combinedParentAccessDenyRules[parentAccessRule.IdentityReference] | parentAccessRule.FileSystemRights; 
      else 
       combinedParentAccessDenyRules.Add(parentAccessRule.IdentityReference, parentAccessRule.FileSystemRights); 
    } 

    // combine child access rules 

    Dictionary<IdentityReference, FileSystemRights> combinedChildAccessAllowRules = new Dictionary<IdentityReference, FileSystemRights>(); 
    Dictionary<IdentityReference, FileSystemRights> combinedChildAccessDenyRules = new Dictionary<IdentityReference, FileSystemRights>(); 
    foreach (FileSystemAccessRule childAccessRule in childAccessControl.GetAccessRules(true, true, typeof(NTAccount))) 
    { 
     if (childAccessRule.AccessControlType == AccessControlType.Allow) 
      if (combinedChildAccessAllowRules.ContainsKey(childAccessRule.IdentityReference)) 
       combinedChildAccessAllowRules[childAccessRule.IdentityReference] = combinedChildAccessAllowRules[childAccessRule.IdentityReference] | childAccessRule.FileSystemRights; 
      else 
       combinedChildAccessAllowRules.Add(childAccessRule.IdentityReference, childAccessRule.FileSystemRights); 
     else 
      if (combinedChildAccessDenyRules.ContainsKey(childAccessRule.IdentityReference)) 
       combinedChildAccessDenyRules[childAccessRule.IdentityReference] = combinedChildAccessDenyRules[childAccessRule.IdentityReference] | childAccessRule.FileSystemRights; 
      else 
       combinedChildAccessDenyRules.Add(childAccessRule.IdentityReference, childAccessRule.FileSystemRights); 
    } 

    // compare combined rules 

    accessAllowRulesGainedByChild = new Dictionary<IdentityReference, FileSystemRights>(); 
    foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedChildAccessAllowRule in combinedChildAccessAllowRules) 
    { 
     if (combinedParentAccessAllowRules.ContainsKey(combinedChildAccessAllowRule.Key)) 
     { 
      FileSystemRights accessAllowRuleGainedByChild = combinedChildAccessAllowRule.Value & ~combinedParentAccessAllowRules[combinedChildAccessAllowRule.Key]; 
      if (accessAllowRuleGainedByChild != default(FileSystemRights)) 
       accessAllowRulesGainedByChild.Add(combinedChildAccessAllowRule.Key, accessAllowRuleGainedByChild); 
     } 
     else 
     { 
      accessAllowRulesGainedByChild.Add(combinedChildAccessAllowRule.Key, combinedChildAccessAllowRule.Value); 
     } 
    } 

    accessDenyRulesGainedByChild = new Dictionary<IdentityReference, FileSystemRights>(); 
    foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedChildAccessDenyRule in combinedChildAccessDenyRules) 
    { 
     if (combinedParentAccessDenyRules.ContainsKey(combinedChildAccessDenyRule.Key)) 
     { 
      FileSystemRights accessDenyRuleGainedByChild = combinedChildAccessDenyRule.Value & ~combinedParentAccessDenyRules[combinedChildAccessDenyRule.Key]; 
      if (accessDenyRuleGainedByChild != default(FileSystemRights)) 
       accessDenyRulesGainedByChild.Add(combinedChildAccessDenyRule.Key, accessDenyRuleGainedByChild); 
     } 
     else 
     { 
      accessDenyRulesGainedByChild.Add(combinedChildAccessDenyRule.Key, combinedChildAccessDenyRule.Value); 
     } 
    } 

    accessAllowRulesGainedByParent = new Dictionary<IdentityReference, FileSystemRights>(); 
    foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedParentAccessAllowRule in combinedParentAccessAllowRules) 
    { 
     if (combinedChildAccessAllowRules.ContainsKey(combinedParentAccessAllowRule.Key)) 
     { 
      FileSystemRights accessAllowRuleGainedByParent = combinedParentAccessAllowRule.Value & ~combinedChildAccessAllowRules[combinedParentAccessAllowRule.Key]; 
      if (accessAllowRuleGainedByParent != default(FileSystemRights)) 
       accessAllowRulesGainedByParent.Add(combinedParentAccessAllowRule.Key, accessAllowRuleGainedByParent); 
     } 
     else 
     { 
      accessAllowRulesGainedByParent.Add(combinedParentAccessAllowRule.Key, combinedParentAccessAllowRule.Value); 
     } 
    } 

    accessDenyRulesGainedByParent = new Dictionary<IdentityReference, FileSystemRights>(); 
    foreach (KeyValuePair<IdentityReference, FileSystemRights> combinedParentAccessDenyRule in combinedParentAccessDenyRules) 
    { 
     if (combinedChildAccessDenyRules.ContainsKey(combinedParentAccessDenyRule.Key)) 
     { 
      FileSystemRights accessDenyRuleGainedByParent = combinedParentAccessDenyRule.Value & ~combinedChildAccessDenyRules[combinedParentAccessDenyRule.Key]; 
      if (accessDenyRuleGainedByParent != default(FileSystemRights)) 
       accessDenyRulesGainedByParent.Add(combinedParentAccessDenyRule.Key, accessDenyRuleGainedByParent); 
     } 
     else 
     { 
      accessDenyRulesGainedByParent.Add(combinedParentAccessDenyRule.Key, combinedParentAccessDenyRule.Value); 
     } 
    } 

    if (accessAllowRulesGainedByChild.Count > 0 || accessDenyRulesGainedByChild.Count > 0 || accessAllowRulesGainedByParent.Count > 0 || accessDenyRulesGainedByParent.Count > 0) 
     return false; 
    else 
     return true; 
} 
+0

Я подумал, что сначала это показалось немного абсурдным, но я в конечном итоге использовал его. Благодаря! –

+0

BTW, я сделал его методом расширения в FileSystemSecurity, чтобы его можно было использовать как для файлов, так и для каталогов. Я также добавил параметры, чтобы includeExplicit и includeInherited параметры для вызовов GetAccessRules можно было изменить. 'public static bool IsEqual (этот FileSystemSecurity sourceAccessControl, FileSystemSecurity destAccessControl, bool includeExplicit, bool includeInherited)' –

Смежные вопросы