Аутентификация из Active Directory, но авторизация ролей из базы данных SQL в MVC

Я новичок в MVC. Я искал и не нашел решения, которое соответствует моим требованиям.

Я разрабатываю веб-портал для внутреннего использования нашей командой, который использует аутентификацию Windows AD для входа в систему. Однако для доступа на основе ролей я создал локальную базу данных, которая может возвращать сведения о роли для пользователя. Я создал собственный фильтр авторизации, который позволяет мне обрабатывать авторизацию на основе роли пользователя. Этот фильтр запрашивает данные из БД, однако проблема с этим подходом заключается в том, что он будет пытаться получить данные из БД для каждого запроса к контроллеру, что делает его дорогостоящим.

Как я могу сохранить данные пользователя, полученные из БД, в токене, чтобы мне не приходилось запрашивать БД для каждого запроса и использовать значения токена внутри фильтра авторизации. Кроме того, я могу использовать значения, полученные для пользователя из базы данных, в любом другом месте приложения. (Есть некоторые другие данные для пользователя, которые у нас есть в базе данных).

Если кто-то может предложить лучший способ добиться этого, пожалуйста, помогите.

Вот код, который я сейчас использую внутри фильтра авторизации:

public class AuthorizeRole : AuthorizeAttribute
{
    private bool _authenticated;
    private bool _authorized;

    public string InRoles { get; set; }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);

        if (_authenticated && !_authorized)
        {
            filterContext.Result = new RedirectResult("/account/error");
        }
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        _authenticated = base.AuthorizeCore(httpContext);

        if (_authenticated)
        {
            if (string.IsNullOrEmpty(InRoles))
            {
                _authorized = true;
                return _authorized;
            }

            if (!string.IsNullOrEmpty(httpContext.User.Identity.Name))
            {
                string NTID = httpContext.User.Identity.Name.Split('\\')[1];
                var roles = InRoles.Split(',');

                using (Models.UserAuthEntities userAuthEntities = new Models.UserAuthEntities())
                {
                    try
                    {
                        ObjectResult<Models.Validate_User_Login_Result> userResults = userAuthEntities.Validate_User_Login(NTID);
                        var user = userResults.FirstOrDefault(all => all.NTID == NTID);

                        if (user == null)
                        {
                            _authorized = false;
                            return _authorized;
                        }
                        else
                        {
                            if (roles.Contains(user.Role))
                            {
                                return _authorized;
                            }
                        }
                    }
                    catch (Exception)
                    {
                        _authorized = false;
                        return _authorized;
                    }
                }
            }
            else
            {
                _authorized = false;
                return _authorized;
            }
        }

        _authorized = false;
        return _authorized;
    }
}

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

Я нашел это решение по адресу: этот сайт, но там оно используется для групп AD.

Я относительно новичок в Azure AD, но как насчет сохранения сведений о роли в TempData, а затем передачи их на каждую страницу, где они могут вам понадобиться? Возможно, слишком просто, или мне не хватает того, что вы хотите сделать?

AxleWack 13.03.2019 10:22

Это не имеет ничего общего с Azure AD. Это локальное AD. Что касается сохранения сведений о ролях в TempData, не могли бы вы рассказать мне, как это сделать (извините, я новичок в этом) с некоторым примером кода и где использовать этот код.

SavindraSingh 13.03.2019 11:04

Ах, извините... В данный момент я занят работой над Azure AD, поэтому, когда вы сказали Active Directory, я неправильно понял. Мои извинения. Таким образом, в вашем ActionResult вы можете установить TempData следующим образом (просто пример): TempData["RoleName"] = "User"; Затем вы можете использовать его следующим образом: string userRoleName = TempData["RoleName"].ToString(); - Опять же, не уверен, что это то, что вы ищете, но таким образом вы можете передавать данные из одного контроллер к другому без включения его в ваш URL-адрес.

AxleWack 13.03.2019 11:10

Но нам нужно проверить роль, прежде чем мы достигнем результата действия, верно! В коде, который я разместил, я проверяю AuthorizeAttribute, находится ли пользователь в роли или нет, и это происходит даже до достижения результата действия для любого контроллера. Теперь вопрос в том, где я должен установить TempData.

SavindraSingh 13.03.2019 11:46

@SavindraSingh, вы используете .NET Core?

Soren 13.03.2019 12:28

Нет. Я использую только Asp.net MVC.

SavindraSingh 13.03.2019 16:06

@SavindraSingh вы используете SignInManager или что-то подобное для управления входом пользователя в систему?

jcruz 15.03.2019 15:38

Я не знаю, что такое SignInManager. Я использую аутентификацию Windows для аутентификации пользователя, но мне нужно проверить таблицу базы данных для проверки доступа на основе ролей.

SavindraSingh 16.03.2019 02:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
8
816
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Во-первых, вы можете рассмотреть возможность использования групп безопасности AD для управления доступом. Таким образом, OPS сможет продолжать поддерживать доступ на знакомой, проверенной временем платформе, и вам не придется писать собственный интерфейс определения безопасности.

Что касается сохранения безопасности MVC Все, что вам нужно сделать, это добавить ручной вход в систему для выполнения вышеуказанной логики, а затем вы используете встроенный поставщик членства (для любой версии MVC, которую вы используете) для входа пользователя в систему. MVC будет поддерживать состояние входа в систему. и токенизации для вас, и вы можете указать такие вещи, как тайм-аут в web.config (или settings.json в Core).

Извините, у меня нет примера кода для иллюстрации.

Ранее у меня были планы использовать группы AD. Однако у нашей компании уже есть база данных, которая использовалась для некоторых других приложений, и в соответствии с требованиями я должен использовать ее. Можем ли мы использовать детали роли из базы данных, если да, то я не знаю, как это сделать.

SavindraSingh 02.03.2019 11:23
Ответ принят как подходящий

Я проверил файл cookie в переопределяющей версии метода AuthorizeCore, теперь он работает:

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        string cookieName = FormsAuthentication.FormsCookieName;
        HttpCookie authCookie = httpContext.Request.Cookies[cookieName];
        _authenticated = base.AuthorizeCore(httpContext);
        string authToken = httpContext.Request.Headers["Auth-Token"];

        if (_authenticated)
        {
            if (authCookie == null)
            {
                if (string.IsNullOrEmpty(InRoles))
                {
                    _authorized = true;
                    return _authorized;
                }

                if (!string.IsNullOrEmpty(httpContext.User.Identity.Name))
                {
                    string NTID = httpContext.User.Identity.Name.Split('\\')[1];
                    var roles = InRoles.Split(',');

                    using (Models.UserAuthEntities userAuthEntities = new Models.UserAuthEntities())
                    {
                        try
                        {
                            ObjectResult<Models.Validate_User_Login_Result> userResults = userAuthEntities.Validate_User_Login(NTID);
                            var user = userResults.FirstOrDefault(all => all.NTID == NTID);

                            if (user == null)
                            {
                                _authorized = false;
                                return _authorized;
                            }
                            else
                            {
                                if (roles.Contains(user.Role))
                                {
                                    _authorized = true;
                                    return _authorized;
                                }
                            }
                        }
                        catch (Exception)
                        {
                            _authorized = false;
                            return _authorized;
                        }
                    }
                }
                else
                {
                    _authorized = false;
                    return _authorized;
                }
            }
        }

        _authorized = false;
        return _authorized;
    }

Другие вопросы по теме