У меня есть веб-сайт, который пытается получить документы из папки, доступной только для определенных групп/пользователей AD. Учитывая, что пользователь прошел проверку подлинности с помощью проверки подлинности Windows, я хочу попытаться проверить, есть ли у него доступ к определенному местоположению, и при необходимости отображать/скрывать документы. У меня сложилось впечатление, что при использовании проверки подлинности Windows и олицетворения ASP.NET будут использоваться учетные данные текущего пользователя при выполнении запроса, а не учетные данные пула приложений, но это, похоже, не так, потому что я администратор, способный открывая папки с ограниченным доступом в проводнике Windows, но я не могу прочитать их из своего приложения.
Есть ли способ использовать учетные данные текущего запрашивающего пользователя для доступа к файлам в локальной файловой системе?
В моем web.config:
<appSettings>
<add key = "documentFolder" value = "C:\Users\auser\source\repos\myapp\myapp\docs\folder1,C:\Users\auser\source\repos\myapp\myapp\docs\folder2,C:\Users\auser\source\repos\myapp\myapp\docs\secured" />
<add key = "securityFolder" value = "C:\Users\auser\source\repos\myapp\myapp\docs\secured"/>
</appSettings>
<system.web>
<authentication mode = "Windows" />
<identity impersonate = "true"/>
<authorization>
<deny users = "?" />
</authorization>
</system.web>
Я пытаюсь получить доступ к файлам в двух местах. Во-первых, я их индексирую (пока это запускается из Application_Start):
var dirs = ConfigurationManager.AppSettings["documentFolder"].ToString().Split(',');
foreach (var dir in dirs)
{
foreach (var file in Directory.GetFiles(dir, "*.pdf", SearchOption.TopDirectoryOnly))
{
try
{
FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read); // <-- Fails with "Access to the path 'C:\Users\auser\source\repos\myapp\myapp\docs\secured' is denied."
}
catch (Exception ex)
{
logger.Error("Failed to read file.", ex);
}
}
}
Позже я пытаюсь проверить, есть ли у пользователя доступ:
protected void Button1_Click(object sender, EventArgs e)
{
bool canSeeSecurityDocuments;
try
{
System.Security.AccessControl.DirectorySecurity ds = Directory.GetAccessControl(ConfigurationManager.AppSettings["securityFolder"].ToString()); <-- Fails with "Attempted to perform an unauthorized operation."
canSeeSecurityDocuments = true;
}
catch (Exception ex)
{
canSeeSecurityDocuments = false;
}
}
Из промона:
Desired Access: Read Attributes, Read Control
Disposition: Open
Options: Open Reparse Point
Attributes: n/a
ShareMode: Read, Write, Delete
AllocationSize: n/a
Impersonating: mydomain\myuserid <- redacted, but correct.
Основываясь на исследованиях интегрированных и классических конвейеров, я переместил вызов GetFiles
в другое место и завернул его в WindowsImpersonationContext
, чтобы посмотреть, не приведет ли это к олицетворению, чего не произошло. (от этот ТАК ответ):
var current = System.Security.Principal.WindowsIdentity.GetCurrent();
logger.Debug(current.Name); <-- This is my identity
WindowsIdentity clientId = (WindowsIdentity)User.Identity;
using (WindowsImpersonationContext wic = clientId.Impersonate())
{
current = System.Security.Principal.WindowsIdentity.GetCurrent();
logger.Debug(current.Name); <-- This is still my identity
// call to GetFiles, as above. Still fails.
}
current = System.Security.Principal.WindowsIdentity.GetCurrent();
logger.Debug(current.Name); <-- still me. Nothing seems to change.
Application_Start не будет работать в контексте пользователя. Олицетворение приведет к тому, что запросы будут выполняться под вошедшим в систему пользователем, но не под Application_Start.
@Rich-Lang, я добавил встроенные сообщения об исключениях. "securityFolder" является подпапкой "documentFolder". У меня есть доступ к файлам в папке «documentFolder», но не в папке «securityFolder».
Я только что перечитал ваш пост, и вы говорите: «Позднее ...» Это значит, что это также выполняется в вашем Application_Start? Если да, то это 100% ваша проблема.
@Rich-Lang, нет, «позже» происходит от обработчика события клика. Код снова обновлен.
Сообщение об ошибке, которое вы показываете, — это то, что я получаю, когда отключаю олицетворение. Я бы рекомендовал получить трассировку ProcMon (docs.microsoft.com/en-us/sysinternals/downloads/procmon) и изучить записи, в которых W3WP.exe пытается подключиться к вашей папке. Я ожидаю, что вы получите отказ в доступе, но взгляните на свойства, чтобы увидеть, выдает ли он себя за пользователя или нет.
@Rich-Lang, обновленный вопрос с результатами procmon. Есть ли шанс, что GetAccessControl не удастся использовать для каталога, к которому у меня действительно есть доступ?
Внимательно прочитайте docs.microsoft.com/en-us/dotnet/api/… и посмотрите, выделяется ли что-нибудь. Я заметил, что запись ProcMon ищет доступ ReadAttributes. Из приведенной выше ссылки: > В средах NTFS ReadAttributes и ReadExtendedAttributes предоставляются пользователю, если у пользователя есть права ListDirectory в родительской папке. Чтобы запретить ReadAttributes и ReadExtendedAttributes, запретите ListDirectory в родительском каталоге.
Проблема заключалась в том, что я использовал пул потоков для выполнения некоторой фоновой работы (индексирование файлов). Похоже, согласно этому ответу SO, что пул потоков не переносит учетные данные, которые использовались для его создания. Я должен был проверить в фактическом потоке, чтобы увидеть, каков был контекст...
У вас есть подробности о конкретном исключении, которое выбрасывается? Я заметил, что вы используете «documentFolder» в одном примере и «securityFolder» в другом. Вы уверены, что это проблема отказа в доступе?