Есть ли лучший способ реализовать доступ на основе ролей в ASP.NET Framework? - PullRequest
0 голосов
/ 26 июня 2019

По сути, я провел последние несколько дней, пытаясь понять, как добавить простые роли администратора и участника на веб-сайт, который я разрабатываю для друга.(Я использую ASP.NET Framework 5.2.7.0).Я знаю, что у Microsoft есть хорошая встроенная функция доступа на основе ролей, которая позволяет вам поместить что-то вроде [Authorize Role=("Admin") в верхнюю часть контроллера;однако я не смог заставить его работать вообще, и большинство ресурсов, которые я нашел, для ASP.NET Core.

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

 [Authorize]
    public class AdminController : Controller
    {
        private LDSXpressContext db = new LDSXpressContext();

        public ActionResult AdminPortal()
        {
            IsAdmin();
            return View();
        }

        private ActionResult IsAdmin()
        {
            string name = User.Identity.Name;
            //The User.Identity.Name stores the user email when logged in
            var currentUserObject = db.accounts.Where(x => x.clientEmail == name);

            Account currentUser = new Account();
            foreach (var user in currentUserObject)
            {
                //I loop through the results, even though only one user should 
                //be stored in the var CurrentUserObject because it's the only 
                //way I know how to assign it to an object and get its values.
                currentUser = user;
            }

            if (currentUser.role == 2) //the number 2 indicates admin in my db
            {
                return null;
            }
            else
            {
           //Even when this is hit, it just goes back and returns the 
           //AdminPortal view
                return RedirectToAction("Index", "Home");
            }
        }
    }

Теперь я почти уверен, что это НЕочень безопасный способ проверить, является ли зарегистрированный пользователь администратором, но я надеялся, что это по крайней мере сработает.Моя идея заключалась в том, что когда кто-то пытался получить доступ к AdminPortal, метод IsAdmin запускался и проверял, является ли пользователь администратором в базе данных.Если это так, то он возвращает значение NULL, и отображается представление AdminPortal. Если они не являются администраторами, они перенаправляются в представление Index на домашней странице.Однако страница AdminPortal всегда отображается для любого пользователя, и это тоже не работает.Я даже вошел в код и наблюдал, как он запускается через действие return RedirectToAction("Index", "Home");, но затем он возвращается к методу AdminPortal и просто возвращает представление AdminPortal.Поэтому мой вопрос:

1) Если у кого-то есть опыт работы с доступом на основе ролей в ASP.NET Framework, я хотел бы получить несколько советов о том, как его настроить

или,

2) Если ничего не помогает, и мне нужно использовать мой хакерский метод, почему он продолжает возвращать AdminView, даже если пользователь не является администратором.

** Примечание: я знаю, что мог бы создать функцию, которая возвращает истину или ложь, если пользователь является администратором, или нет, а затем иметь оператор if / else в контроллере AdminPortal, который будет возвращаться при просмотре для истиныи другое для false, однако я не хочу внедрять это в каждый ActionMethod, было бы неплохо сохранить его до одной строки или просто на [Authorize Role="Admin] над контроллером, если это возможно.

Большое спасибо, ребята, за любую предоставленную помощь, я уже несколько дней пытаюсь найти и исправить это и решил обратиться к сообществу!

1 Ответ

0 голосов
/ 26 июня 2019

Как минимум, вы захотите внести некоторые изменения в то, что вы делаете:

[Authorize]
public class AdminController : Controller
{
    public ActionResult AdminPortal()
    {
        if(IsAdmin())
        {
            return View();
        }

        return RedirectToAction("Index", "Home");
    }

    private bool IsAdmin()
    {
        bool isAdmin = false;

        using(LDSXpressContext db = new LDSXpressContext())
        {
            string name = User.Identity.Name;

            //The User.Identity.Name stores the user email when logged in

            // @see https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.singleordefault
            var currentUser = db.accounts.SingleOrDefault(x => x.clientEmail.Equals(name, StringComparison.OrdinalIgnoreCase));

            // If the email doesn't match a user, currentUser will be null
            if (currentUser != null) 
            {
                //the number 2 indicates admin in my db
                isAdmin = currentUser.role == 2;
            }
        }

        return isAdmin;
    }
}

Во-первых, экземпляры DbContext предназначены для использования, самое большее, за время существования HTTP-запроса. Перемещение его с уровня класса / контроллера и помещение его в блок использования позволяет убедиться, что он правильно расположен.

Затем вашей IsAdmin функции действительно нужно вернуть значение true / false на основе вашего поиска, и затем действие AdminPortal может решить, что делать с этим результатом.

Поскольку электронная почта кажется уникальным полем в вашей таблице, используйте расширение SingleOrDefault или FirstOrDefault LINQ для извлечения одной совпадающей записи. Какой из них вы используете, зависит от вас, но если это действительно уникальное значение, SingleOrDefault имеет больше смысла (будет выброшено исключение, если будет найдено более одной строки). Использование флага StringComparison с методом расширения String.Equals делает поиск нечувствительным к регистру. Есть несколько специфичных для данной культуры версий этого, но здесь я бы обычно использовал порядковое соответствие.

Реализация некоторой версии платформы Identity слишком длинна для ответа здесь, но можно реализовать схему аутентификации на основе утверждений без излишней работы. Это, вероятно, требует отдельного ответа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...