Пользовательские сессии с Vaadin Flow - PullRequest
0 голосов
/ 18 января 2019

В настоящее время я являюсь начинающим Java-разработчиком, который хочет заняться разработкой Vaadin и в настоящее время пытается реализовать вход в систему через пользовательский сеанс для моего приложения. Я прочитал о содержании, касающемся использования VaadinServlets для этого: https://vaadin.com/docs/v10/flow/advanced/tutorial-application-lifecycle.html.

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

Однако мои цели для приложения немного отличаются:

[Вариант использования]

1. Пользователь входит в систему со своими учетными данными.

2.Пересылки на SecuredPage (которая создаст сеанс пользователя, в котором хранится имя пользователя и получит токен?)

3. Через 2-3 минуты бездействия Пользователь будет вынужден выйти из SecuredPage, а сессия закрывается?

@WebServlet(urlPatterns = "/*", name = "VaadinFlowServlet", asyncSupported = true)
@VaadinServletConfiguration(heartbeatInterval = 5, productionMode = false)
public class LoginServlet extends VaadinServlet implements SessionInitListener, SessionDestroyListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoginServlet.class);

    // <Method> ::servletInitialized():: -> handles most of the servlet customization. (write my servlet customization under this function.
    //          ::getService()::         -> returns a VaadinServletService type?
    //          ::addSessionInitListener(this)::    -> An event listener that can be registered to a VaadinService to get an event -> when a new Vaadin service session is initialized for that service.
    //          ::addSessionDestroyListener(this):: -> A listener that gets notified when a Vaadin service session is no longer used.
    @Override
    protected void servletInitialized() throws ServletException {
        super.servletInitialized();
        getService().addSessionInitListener(this);
        getService().addSessionDestroyListener(this);

    }

    // <Method>     ::sessionInit::      -> Starts Session?
    // <Parameter>  ::SessionInitEvent:: -> Event gets fired when a new Vaadin service session is initialized for a Vaadin service.
    @Override
    public void sessionInit(SessionInitEvent event) throws ServiceException{
        // Do Session start stuff here
        // Creates a Session?

        LOGGER.info("session init() "
                + " Session-ID: " + event.getSession().getSession().getId()
                + " CSRF: " + event.getSession().getCsrfToken());

    }

    // <Method>     ::sessionDestroy:: -> Stops Session?
    // <Parameter>  ::SessionDestroyEvent:: -> Event fired when a Vaadin service session is no longer in use.
    @Override
    public void sessionDestroy(SessionDestroyEvent event) {
        // Do session end stuff here
        LOGGER.info("session destory()");
    }

    }

1 Поэтому мне было интересно, если кто-нибудь может помочь мне лучше понять этот вопрос? Полностью оценен

1 Ответ

0 голосов
/ 20 января 2019

ТЛ; др

Простое существование пользовательского объекта входа в систему пользователя, хранящегося в качестве атрибута в хранилище значений ключей вашего VaadinSession, представляет пользователя, успешно прошедшего аутентификацию. Нет необходимости во всем написанном вами коде слушателя сессии.

Пусть Ваадин сделает тяжелую работу

Я подозреваю, что вы слишком усердно работаете.

Нет необходимости для слушателей вашего сеанса. Vaadin обрабатывает почти все детали Java-сервлета от нашего имени.

Нет необходимости в перенаправлениях . Как разработчик Vaadin, вы полностью контролируете содержимое, отображаемое во вкладке / окне браузера, так что вы можете переключаться между формой входа и основным содержимым приложения. Предостережение: я новичок в функции @Route в Vaadin Flow, так что может быть более изящный способ переключения между входом в систему и основным контентом. И если вы используете @Route для нескольких представлений, каждое из этих представлений должно проверить аутентификацию, как описано ниже.

VaadinSession

В точке входа вашего кода приложения Vaadin получите текущий объект VaadinSession. Этот VaadinSession является оберткой вокруг класса javax.servlet.http.HttpSession, определенного спецификацией Java Servlet . Vaadin автоматически создает экземпляр сеанса, когда браузер пользователя впервые подключается к вашему веб-приложению Vaadin (фактически, Vaadin переносит сеанс, созданный вашим веб-контейнером ). Сеанс автоматически закрывается, когда браузер закрывает свою вкладку / окно, происходит тайм-аут неактивности или вы закрываете сеанс программным способом.

VaadinSession vaadinSession = VaadinSession.getCurrent() ; 

Атрибуты сеанса (хранилище значений ключей)

Опросить значение ключа этого сеансового объекта, известное как «атрибуты». Ключ имеет тип String, а значение имеет тип Object (суперкласс всех объектов Java). После получения объекта Object вы переходите к известному классу. Вы знаете класс, потому что именно ваш код хранит атрибут.

Ваш логин пользователя

Вы бы определили класс для хранения информации, связанной с вашим логином. Возможно, вы назвали это UserLogin.

Что-то вроде:

public class UserLogin {
    // Member values.
    String userName ;
    Instant whenAuthenticated ;

    // Constructor.
    public UserLogin( String userNameArg , Instant whenAuthenticatedArg ) {
        this.userName = userNameArg ;
        this.whenAuthenticated = whenAuthenticatedArg ;
    }
}

Попытка получить объект вашего класса входа в систему из хранилища значений ключей сеанса

Получить такой объект такого типа из хранилища значений ключей атрибутов сеанса.

String attributeName = "my-user-login" ;
UserLogin userLogin = vaadinSession.getAttribute( attributeName ) ;

Вместо того, чтобы придумывать имя атрибута, вы можете просто использовать имя класса. Класс Class позволяет запрашивать имя класса в виде текста.

String attributeName = UserLogin.class.getName() ;
UserLogin userLogin = vaadinSession.getAttribute( attributeName ) ;

Если вы хотите использовать имя класса в качестве ключа таким образом, класс VaadinSession предоставляет ярлык.

UserLogin userLogin = vaadinSession.getAttribute( UserLogin.class ) ;

Проверьте, является ли ваш UserLogin объект нулевым. Если вы получили null, то вы знаете, что еще не сохранили атрибут (или умышленно сохранили ноль).

Если не ноль, это означает, что у вашего пользователя уже сохранен активный UserLogin объект. Как они могли войти в систему уже, если точка входа вашего приложения выполняется? Это может произойти, если пользователь нажмет кнопку Обновить в своем окне браузера. (Научите пользователя не делать этого в одностраничном веб-приложении , например, Vaadin.)

Схема кода для записи

UserLogin userLogin = vaadinSession.getAttribute( UserLogin.class ) ;
if( Objects.isNull( userLogin ) ) {
    … display login form …
    … when authenticated, instantiate a `UserLogin` and store as attribute …
    if( authenticationSuccessful ) {  // Testing some did-user-authenticate variable you defined in your login-form.
        Instant whenAuthenticated = Instant.now() ;  // Capture the current moment in UTC. 
        UserLogin userLogin = new UserLogin( userName , whenAuthenticated ) ;
        VaadinSession.getCurrent().setAttribute( UserLogin.class , userLogin ) ;  // Using class name as the `String` key tracking this `userLogin` object.
        … switch content of the tab/window from authentication form to your main app content …
    } 
} else {  // Else not null. User already authenticated. User may have hit "Reload" button in browser. 
    … display app content … 
    … perhaps log this event … maybe user needs to be trained to not hit Reload on a Single-Page Web App …
}

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

В какой-то момент вы можете найти хук в жизненном цикле всего вашего веб-приложения, прежде чем первый пользователь подключится и / или после того, как последний отключится, узнайте о хуке, определенном в спецификации Java-сервлета. Этот хук представляет собой интерфейс ServletContextListener, где «контекст» означает ваше веб-приложение в целом. Это стандартный материал сервлетов Java, совсем не специфичный для Vaadin, но Vaadin на самом деле является сервлетом (возможно, самым сложным из когда-либо существовавших сервлетов), поэтому применима эта парадигма прослушивания контекста.

Вы пишетекласс, реализующий этот интерфейс, путем написания методов before-first-user и after-last-user. Идентифицируйте свой класс в веб-контейнере, отмечая @WebListener (или альтернативные средства). Переполнение стека поиска, поскольку это уже было рассмотрено несколько раз.

...