Vaadin Flow的用户会话

时间:2019-01-18 01:38:58

标签: vaadin10 vaadin-flow

我目前是一位新兴的Java开发人员,希望参与Vaadin开发,并且目前正在尝试为我的应用程序实现User Session登录。我已经阅读了有关使用VaadinServlet的内容:https://vaadin.com/docs/v10/flow/advanced/tutorial-application-lifecycle.html

在不懈地研究API文档和示例代码之后,我仍然无法理解如何为登录到我的平台的特定用户实施用户会话。据我了解,我可以使用下面实现的方式初始化用户会话。

但是我对应用程序的目标略有不同:

[用例]

1。用户使用其特定的凭据登录。

2.Gets重定向到SecuredPage(它将创建一个存储用户名和检索令牌的User Session)

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 :(得分:1)

tl; dr

仅存在一个自定义的用户登录对象,该对象作为属性存储在VaadinSession的键值存储中,表示用户已成功通过身份验证。不需要您编写的所有会话侦听器代码。

让Vaadin做繁重的事情

我怀疑您太努力了。

您的会话监听器不需要。 Vaadin几乎代表我们处理所有Java Servlet详细信息。

不需要redirects。作为Vaadin开发人员,您可以完全控制浏览器选项卡/窗口中显示的内容,因此可以在登录表单和主要应用程序内容之间切换。注意:我是Vaadin Flow的@Route功能的新手,因此该功能可能会有更巧妙的方式在登录和主要内容之间切换。而且,如果您将@Route用于多个视图,则这些视图中的每个视图都应按照以下所述测试身份验证。

VaadinSession

在Vaadin应用程序代码的入口点,检索当前的VaadinSession对象。该VaadinSessionjavax.servlet.http.HttpSession定义的Java Servlet spec类的包装。当用户的浏览器首次连接到您的Vaadin网络应用程序时,Vaadin会自动实例化会话(实际上,Vaadin会包装您的web container实例化的会话)。当浏览器关闭其选项卡/窗口,不活动超时或您以编程方式关闭会话时,会话将自动关闭。

VaadinSession vaadinSession = VaadinSession.getCurrent() ; 

会话属性(键值存储)

询问该会话对象的key-value存储区,称为“属性”。键的类型为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类可让您ask for the name作为文本类。

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

如果要通过这种方式使用类名作为键,则VaadinSession类提供了快捷方式。

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

检查您的UserLogin对象是否为空。如果检索到null,则表明您尚未存储属性(或故意存储null)。

如果不为null,则表示您的用户已经存储了一个活动的UserLogin对象。如果您的应用程序的入口点正在执行,如何登录?如果用户在其浏览器窗口中点击重新加载按钮,则可能会发生这种情况。 (训练您的用户不要在Vaadin之类的single-page web app上这样做。)

要编写的代码概述

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 …
}

顺便说一下,以上有关会话的讨论仅限于每个用户在单个Web浏览器标签/窗口中与您的Web应用程序的连接。

在第一个用户连接之前和/或最后一个用户断开连接之后,您可能会在某个时候寻找整个Web应用程序生命周期的钩子,以了解Java Servlet规范中定义的钩子。该挂钩是ServletContextListener界面,其中“上下文”表示您的整个Web应用程序。这是标准的Java Servlet内容,完全不是Vaadin所特有的,但是Vaadin实际上是一个Servlet(也许是有史以来最复杂的Servlet),因此适用于上下文侦听器范例。

您通过编写前一个用户和后一个用户方法来编写实现该接口的类。通过注释@WebListener(或替代方法),将您的班级识别为Web容器。搜索堆栈溢出,因为已经对此进行了多次讨论。