Как обрабатывать доступ к представлениям, если пользователь еще не аутентифицирован?

Главная страница моего Vaadin 14 — это MainView с корневым маршрутом.

MainView используется как «шаблон» для другого представления (с layout = MainView.class), поэтому я вижу его скорее как «абстрактное» представление, которое не должно инициализироваться само по себе и используется только для других представлений в качестве макета.

Теперь проблема: если пользователь обращается к MainView, BeforeEnterEvent вызывается ПОСЛЕ конструктора. Это может привести к возникновению исключений, поскольку пользователь еще не аутентифицирован, а конструктор уже выполняет такие действия, как создание вкладок.

Есть ли способ запретить пользователю доступ к маршруту MainView или событию, которое выполняется до вызова конструктора? Доступ к представлению разрешен только в том случае, если пользователь прошел аутентификацию.

@Route("")
public class MainView extends AppLayout implements BeforeEnterObserver {

public MainView() {
    super();

    // Creates all the Tabs that are used in the MainView, may throw exception if the user calls the URL of this View before authenticated
    setupView();
}

...

@Override
public void beforeEnter(BeforeEnterEvent event) {
    // Reroute to Login if User is NOT authenticated
}
}

@Route(value = "foo", layout = MainView.class)
public class OtherView {

Обновление:

Исправление выпущено как экспериментальная функция в Vaadin 14.2.


person Michael Kemmerzell    schedule 14.01.2020    source источник


Ответы (3)


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

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

Я бы предложил переместить код настройки представления в onAttach. Если вы хотите запустить код установки только один раз, вы можете использовать AttachEvent#isInitialAttach, чтобы выполнить код только при первом подключении.

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

Чтобы не создавать никаких представлений, вы можете добавить прослушиватель непосредственно в пользовательский интерфейс, используя UI#addBeforeEnterListener, как только пользовательский интерфейс будет создан, используя Прослушиватель инициализации пользовательского интерфейса. Опять же, только когда исправление было выпущено.

person Erik Lumme    schedule 14.01.2020
comment
Спасибо за ссылку на проблему. Я не знал, что это известная проблема. Я дам ему попробовать :) - person Michael Kemmerzell; 14.01.2020

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

Но предлагаемое решение также добавляет в представления beforeEnterListener, поэтому я не думаю, что ваша проблема решена с помощью этого.
Решение вашей проблемы может заключаться в создании пользовательского исключения (давайте назовем его NotAuthorizedException для дальнейшего использования) в конструктор MainView, если пользователь не авторизован. Затем вы позволяете своему LoginView реализовать HasErrorParameter<NotAuthorizedException>

person kscherrer    schedule 14.01.2020

Я смог временно исправить это с дополнительной проверкой аутентификации. Возможно, это не лучшее решение, но пока оно работает. В будущем ответ @Tazavoo должен быть реализован.

public MainView() {
    super();
    if (!isAuthenticated()) 
       return;

    setupView();
}
person Michael Kemmerzell    schedule 15.01.2020