Asp.net - доступ к некоторой папке в общем доступе к файлу на основе аутентифицированного пользователя

У меня есть веб-приложение asp.net с проверкой подлинности форм, а пользователи (учетные данные) проверяются на активный каталог, имя пользователя - это атрибут samAccountName из AD. Теперь мне нужно разрешить пользователям получать доступ к некоторым файлам, находящимся в общем доступе к файлу, где каждый пользователь имеет свою собственную папку.

Первое доказательство концепции работает следующим образом:

  • appPool в IIS настроен для работы под некоторым пользователем домена, и этому пользователю был предоставлен доступ к файловому ресурсу и всем пользовательским папкам с правами доступа к ресурсам

  • когда пользователь регистрируется в веб-приложении, только содержимое папки на пути "\\ myFileServer\username" видимо для него. И при загрузке файлов они сохраняются в "\\ myFileServer\username".

Пока это работает, похоже, что оно вообще не безопасно. Первая проблема заключается в том, что пользователь, у которого работает пул приложений, имеет доступ к папкам всех пользователей. И еще большая проблема заключается в том, что только имя пользователя определяет, в какую папку у вас есть доступ.

Итак, мой вопрос в том, каков правильный/лучший способ сделать это? Я читал о выдаче себя за пользователя, но это не рекомендуется, если я правильно понял? И у меня нет аутентификации Windows, поскольку веб-приложение должно быть доступно из Интернета.

Ответ 1

Я рекомендую не запускать приложение под учетной записью пользователя, а создавать учетную запись приложения, в соответствии с которой она работает с соответствующими правами R/W, и отделить человека, который дает эти права от команды разработчиков.

В рамках аутентификации приложения: после получения запроса GET/POST вы можете проверить путь, по которому текущий пользователь будет читать/записывать данные, и перекрестно ссылаться на это с помощью пути, которому пользователь имеет право читать/писать из, Если они неверны, верните ответ 401 NOT AUTHORIZED, иначе выполняйте операцию так же, как и сейчас.

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

Ответ 2

Из описания вашей проблемы я думаю, что Custom HttpHandlers - правильный выбор для вас. Вы не указали, какие файлы будут присутствовать в вашей папке, для краткости я отвечу, предположив, что у него будут файлы PDF.

Как вы уже упоминали, у вашего приложения будут разные пользователи, поэтому для этого вам нужно использовать встроенный диспетчер аутентификации .NET и роль поставщика ролей. С помощью простой настройки безопасности мы поместим файл PDF в веб-приложение за защищенной папкой web.config. Затем создайте настраиваемый обработчик HTTP, чтобы ограничить доступ к статическому документу только тем пользователям, которым разрешено просматривать он.

Пример обработчика HTTP:

public class FileProtectionHandler : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        switch (context.Request.HttpMethod)
        {
            case "GET":
            {
                // Is the user logged-in?
                if (!context.User.Identity.IsAuthenticated)
                {
                    FormsAuthentication.RedirectToLoginPage();
                    return;
                }
                string requestedFile = 
                 context.Server.MapPath(context.Request.FilePath);
                // Verify the user has access to the User role.
                if (context.User.IsInRole("User"))
                {
                    SendContentTypeAndFile(context, requestedFile);
                }
                else
                {
                    // Deny access, redirect to error page or back to login 
                     //page.
                    context.Response.Redirect("~/User/AccessDenied.aspx");
                }
                break;
        }
    }
}

Метод SendContentTypeAndFile:

private HttpContext SendContentTypeAndFile(HttpContext context, String strFile)
{
    context.Response.ContentType = GetContentType(strFile);
    context.Response.TransmitFile(strFile);
    context.Response.End();
    return context;
}
private string GetContentType(string filename)
{
    // used to set the encoding for the reponse stream
    string res = null;
    FileInfo fileinfo = new FileInfo(filename);
    if (fileinfo.Exists)
    {
        switch (fileinfo.Extension.Remove(0, 1).ToLower())
        {
            case "pdf":
            {
                res = "application/pdf";
                break;
            }
        }
        return res;
    }
    return null;
}

Последний шаг заключается в том, что вам нужно настроить этот обработчик HTTP в webconfig, и вы можете увидеть больше информации здесь

Вот полный Исходный код

Ответ 3

Архитектура (и предположения) кажется хорошей для низкого/среднего уровня безопасности, но если характер ваших данных очень чувствительный (медицинский и т.д.), моя самая большая забота о безопасности будет заключаться в контроле за сеансами пользователя.

Если вы используете проверку подлинности с использованием форм, вы сохраняете аутентифицированный идентификатор в файле cookie или в токене (или если вы используете липкие сеансы, тогда вы отправляете идентификатор сеанса, но для случая это то же самое). Проблема возникает, если пользователь B имеет физический доступ к машине, на которой работает пользователь A. Если пользователь A покидает это рабочее место (какое-то время или навсегда), и он явно не закрывает сеанс в своем веб-приложении, то его личность осталась на месте, по крайней мере, до тех пор, пока его cookie/токен не истечет, и пользователь B может его использовать поскольку система идентификации ASP.NET не выполнила SignOut. Проблема еще хуже, если вы используете токены для авторизации, потому что во всех печально известных версиях Microsoft Identity System вы несете ответственность за предоставление способа сделать недействительными такие токены (и заставить их исчезнуть с клиентской машины), когда пользователь выберет, так как они останутся действительными до истечения срока его действия. Это может быть устранено (но совершенно не так удовлетворительно для высоких требований безопасности), выдавая короткие живые обновленные токены, но это другая история, и я не знаю, было ли это ваше дело. Если вы собираетесь использовать файлы cookie, тогда, когда пользователь A выдает его, cookie недействителен и удаляется из файла запроса/ответа, поэтому эта проблема устранена. В любом случае вы должны следить за тем, чтобы ваши пользователи закрывали свои сеансы в своем веб-приложении и/или настраивали файлы cookie с короткими сроками или короткими сроками сползания.

Другие проблемы безопасности могут быть связаны с CSRF, которые вы можете запретить использовать инфраструктуру Token Antiforgery Token для ASP.NET, но такие атаки - это методы, которые очень далеки от типичного пользователя (я ничего не знаю о характер вашего пользователя и если ваше приложение открыто для публики в Интернете или оно доступно только в интрасети), но если вы беспокоитесь о таких специализированных атак и имеете такие конфиденциальные данные, возможно, вам стоит пойти с чем-то более сложным, чем проверка подлинности форм (например, два фактора, биометрические и т.д.)