我目前是一位新兴的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 所以我想知道是否有人可以帮助我更好地理解这件事?完全赞赏
答案 0 :(得分:1)
仅存在一个自定义的用户登录对象,该对象作为属性存储在VaadinSession
的键值存储中,表示用户已成功通过身份验证。不需要您编写的所有会话侦听器代码。
我怀疑您太努力了。
您的会话监听器不需要。 Vaadin几乎代表我们处理所有Java Servlet详细信息。
不需要redirects。作为Vaadin开发人员,您可以完全控制浏览器选项卡/窗口中显示的内容,因此可以在登录表单和主要应用程序内容之间切换。注意:我是Vaadin Flow的@Route
功能的新手,因此该功能可能会有更巧妙的方式在登录和主要内容之间切换。而且,如果您将@Route
用于多个视图,则这些视图中的每个视图都应按照以下所述测试身份验证。
VaadinSession
在Vaadin应用程序代码的入口点,检索当前的VaadinSession
对象。该VaadinSession
是javax.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容器。搜索堆栈溢出,因为已经对此进行了多次讨论。