Хобрук: Ваш путь к мастерству в программировании

Запретить прямой доступ по URL к обработчику страницы razor

Я сделал страницу бритвы для выхода пользователей из системы. Когда аутентифицированный пользователь посещает маршрут /account/logout, я хочу показать ему страницу с сообщением об успехе, если пользователь анонимен, то страница не авторизована. Однако эта страница успеха не должна быть доступна путем прямого ввода URL-адреса.

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

public class LogoutModel : CustomPageModel
{
    private readonly SignInManager _signInManager;

    public LogoutModel(SignInManager signInManager) => _signInManager = signInManager;

    public async Task<IActionResult> OnGetAsync()
    {
        if (_signInManager.IsSignedIn(User))
        {
            await _signInManager.SignOutAsync();
            return RedirectToPage("Logout", "Success");
        }

        return Unauthorized();
    }

    public void OnGetSuccess()
    {
    }
}

Как предотвратить прямой доступ к обработчику OnGetSuccess?


Ответы:


1

Задайте этот вопрос, как это возможно.

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

Logout.cshtml.cs

public class LogoutModel : CustomPageModel
{
    private readonly SignInManager _signInManager;

    public LogoutModel(SignInManager signInManager) => _signInManager = signInManager;

    public string StatusMessage { get; set; }

    public async Task<IActionResult> OnGetAsync()
    {
        if (_signInManager.IsSignedIn(User))
        {
            await _signInManager.SignOutAsync();
            StatusMessage = "Successfully logged out!";
            return Page();
        }
        else {
            StatusMessage = "Already logged out!";
            return Page();
        }

    }
}

Logout.cshtml

@page
@model X.LogoutModel

@Model.StatusMessage
26.04.2019
  • Перенаправление на страницы для контекстного статуса - моя проблема, они всегда доступны напрямую. Скажем, если пользователь входит в систему и переходит на страницу 1 (потому что это могло быть сохранено в истории), страница скажет, что она успешно вышла из системы, но этого не произошло, потому что это не прошло через обработчик выхода, который вызывает SignOutAsync(). 27.04.2019
  • Вот почему я предложил [Авторизоваться] для класса Page1, требуя входа в систему для доступа к нему. Или вы можете перенаправить пользователя, если он войдет в систему, войдя в систему. 27.04.2019
  • Вы не можете этого сделать, к тому времени, когда вы перенаправляете на Page1, он больше не аутентифицируется. Сначала я использовал return Page() для отображения содержимого страницы выхода из системы, содержащей сообщение об успешном завершении. Это решило бы проблему, но представило бы другую проблему, когда пользователю предоставляется контент, как если бы он все еще был аутентифицирован (хотя он уже не прошел), пока он не обновит страницу. 27.04.2019
  • Ах да, мой плохой, так что эта альтернатива была плохим предложением. Я отредактировал свой ответ и скорректировал код, чтобы отразить только предложение сообщения о статусе. 27.04.2019

  • 2

    Я решил это с помощью Attribute и IPageFilter, который проверяет заголовок Referer.

    Сначала я создал атрибут

    [AttributeUsage(AttributeTargets.Method)]
    public class ChildHandlerAttribute : Attribute
    {
    }
    

    Затем я украсил им GetOnSuccess() обработчик

    [ChildHandler]
    public void OnGetSuccess()
    {
    }
    

    Затем я реализовал фильтр, проверяющий заголовок Referer на предмет дочерних обработчиков.

    public class ChildHandlerAsyncPageFilter : IAsyncPageFilter
    {
        public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
        {
            var pageHandlerExecutedContext = await next();
    
            if (pageHandlerExecutedContext.HandlerMethod?.MethodInfo.GetCustomAttribute<ChildHandlerAttribute>() == null)
            {
                return;
            }
    
            var referrer = context.HttpContext.Request.Headers["Referer"].ToString();
            var request = pageHandlerExecutedContext.HttpContext.Request;
    
            if (!referrer.StartsWith($"{request.Scheme}://{request.Host}"))
            {
                pageHandlerExecutedContext.Result = new NotFoundResult();
            }
        }
    
        public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) => Task.CompletedTask;
    }
    

    Наконец, я добавил фильтр в конвейер в Startup.cs

    services.AddMvc(options =>
    {
        options.Filters.Add<ChildHandlerAsyncPageFilter>();
    });
    
    29.04.2019

    3

    В вашем сценарии пользователь выходит и перенаправляется как анонимный пользователь. Так что нельзя сказать, что здесь только определенные пользователи имеют доступ к этому действию.

    Вы должны решить это другими способами. например, вы можете установить значение в файле cookie в LogOut Action, а затем проверить Success Action. Для большей безопасности примените шаблон, который MVC использует для CSRF.

    29.04.2019
    Новые материалы

    Dall-E 2: недавние исследования показывают недостатки в искусстве, созданном искусственным интеллектом
    DALL-E 2 — это всеобщее внимание в индустрии искусственного интеллекта. Люди в списке ожидания пытаются заполучить продукт. Что это означает для развития креативной индустрии? О применении ИИ в..

    «Очень простой» эволюционный подход к обучению с подкреплением
    В прошлом семестре я посетил лекцию по обучению с подкреплением (RL) в моем университете. Честно говоря, я присоединился к нему официально, но я редко ходил на лекции, потому что в целом я нахожу..

    Освоение информационного поиска: создание интеллектуальных поисковых систем (глава 1)
    Глава 1. Поиск по ключевым словам: основы информационного поиска Справочная глава: «Оценка моделей поиска информации: подробное руководство по показателям производительности » Глава 1: «Поиск..

    Фишинг — Упаковано и зашифровано
    Будучи старшим ИТ-специалистом в небольшой фирме, я могу делать много разных вещей. Одна из этих вещей: специалист по кибербезопасности. Мне нравится это делать, потому что в настоящее время я..

    ВЫ РЕГРЕСС ЭТО?
    Чтобы понять, когда использовать регрессионный анализ, мы должны сначала понять, что именно он делает. Вот простой ответ, который появляется, когда вы используете Google: Регрессионный..

    Не зря же это называют интеллектом
    Стек — C#, Oracle Опыт — 4 года Работа — Разведывательный корпус Мне пора служить Может быть, я немного приукрашиваю себя, но там, где я живу, есть обязательная военная служба на 3..

    LeetCode Проблема 41. Первый пропущенный положительный результат
    LeetCode Проблема 41. Первый пропущенный положительный результат Учитывая несортированный массив целых чисел, найдите наименьшее пропущенное положительное целое число. Пример 1: Input:..