Vaadin

Vaadin Login Example

A login form is used to process user authentication in a web application.Ccontrary to web pages, web applications could be a complex piece of software and the public nature of the Internet make the user authentication a vital part of any web application. In this example I am going to show you how to implement a login form in Vaadin to protect the secure part of a web application.

1. The tools

  • Java JDK 8
  • Latest Eclipse Mars
  • Vaadin 7.6.4
  • Tomcat Server 8

2. Introduction

A login is a special form that collects user credentials and communicates with an authentication mechanism to check the validity of the credentials, then if the credentials are valid the user is routed to a secure area else if the credentials are invalid the page keep asking for a valid input, there are a multiples approach to this problem.

You can define the number of times a user can retry for invalid credentials from a single username, a browser user-agent, an IP, a mac address, cookies and other user guessing identification methods, you can use MD5 to hash your credentials but the security of the MD5 hash function is severely compromised. The best approach nowadays is to use the HTTP over SSL (https) protocol that create a secure channel over an insecure network for your web application. Vaadin offers a navigation mechanism to manage your views, using that I constructed the login form, in older versions of Vaadin have a LoginForm class but from version 7 and up LoginForm is deprecated.

3. Prerequisites

  • JDK installed
  • Eclipse Mars installed and working
  • Vaadin 7.6.4 plugin installed
  • Tomcat 8 installed and running

4. Set up the project

In the file menu choose File -> New -> Other:

01 New Project
01 New Project

Now from the list choose Vaadin 7 project:

02 Vaadin Project
02 Vaadin Project

Hit next and name your project then hit finish.

5. Coding the example

5.1 Mockup Authentication class

Lets create a mockup authentication class that handle the backend authentication with only one user, you can change it to any needed mechanism.

Authentication.java

package com.example.vaadinlogin;

public class Authentication {
	
	private String username;
	private String password;
	
	public Authentication() {
		setUsername("myuser");
		setPassword("mypass");
	}

	private void setUsername(String username) {
		this.username = username;
	}
	
	private String getUsername(){
		return this.username;
	}

	private void setPassword(String password) {
		this.password = password;
	}
	
	private String getPassword(){
		return this.password;
	}
	
	public Boolean authenticate(String username, String password){
		if(username.equals(getUsername()) && password.equals(getPassword())){
			return true;
		}
		return false;
	}

}

This class have two private String fields for the user and the password, also have the boilerplate setter and getter and a method public Boolean authenticate(String username, String password) that receive two strings as parameters and returns true if the credentials correspond with the mockup user created, here you have space to plug a database or whatever backend you choose to store your users credentials.

5.2 Login Page

Let’s build the login page:

Layout

public class LoginPage extends VerticalLayout implements View {
	private static final long serialVersionUID = 1L;
	public static final String NAME = "";

The login page extends VerticalLayout to place our components and implements View to use a Navigator, more on this later, and have a field NAME to use also in the navigation flow of the application.

Login Panel

		Panel panel = new Panel("Login");
		panel.setSizeUndefined();
		addComponent(panel);

The fields of the login form are inside a Panel so create the panel and add it to the layout.

Login Form

		FormLayout content = new FormLayout();
		TextField username = new TextField("Username");
		content.addComponent(username);
		PasswordField password = new PasswordField("Password");
		content.addComponent(password);

Inside the panel there is a form with a TextField for the username, a PasswordField that is a special kind of text field that allows to hide the user input, the password field is used for the password, I add both fields to the FormLayout content.

Button Send

		Button send = new Button("Enter");
		send.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				if(VaadinloginUI.AUTH.authenticate(username.getValue(), password.getValue())){
					VaadinSession.getCurrent().setAttribute("user", username.getValue());
					getUI().getNavigator().addView(SecurePage.NAME, SecurePage.class);
					getUI().getNavigator().addView(OtherSecurePage.NAME, OtherSecurePage.class);
					Page.getCurrent().setUriFragment("!"+SecurePage.NAME);
				}else{
					Notification.show("Invalid credentials", Notification.Type.ERROR_MESSAGE);
				}
			}
			
		});

I created a Button to check the credentials against the mockup authentication class. The button have a ClickListener() and when the button is pressed, the following things happen: VaadinloginUI.AUTH.authenticate check the credentials, if the credentials are incorrect a Notification is show, is better not to specify what credential is wrong so is a general message with invalid credentials, if the credentials are correct then set the user in the session to keep logged in between page refresh, next add two more views to the navigator. These view are private and you need to be logged to access them and last redirect the page using setting a uri fragment. In this case the uri fragment correspond to the last part of the uri after the “#” character, so I am using the name defined in the page to navigate to that page.

Add components

		content.addComponent(send);
		content.setSizeUndefined();
		content.setMargin(true);
		panel.setContent(content);
		setComponentAlignment(panel, Alignment.MIDDLE_CENTER);

Add the components to the layout and set the panel alignment to the center as is usual in login forms but you can put it on any place of the page.

5.3 Secure page

The secure page is a page to show the private area behavior, in the private area you can have all the pages you need.

The layout

public class SecurePage extends VerticalLayout implements View {
	private static final long serialVersionUID = 1L;
	private Label secure;
	private Label currentUser;
	private Button otherSecure;
	private Button logout;
	public static final String NAME = "Secure";

As before this page use a vertical layout to put the components, it have two labels and two buttons, the label currentUser is used to show the user logged in the application, it have a button to go to the other secure page and a button to logout.

otherSecure Button

		otherSecure = new Button("OtherSecure");
		otherSecure.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				Page.getCurrent().setUriFragment("!"+OtherSecurePage.NAME);
			}
		});

The otherSecure button is used to navigate to the other private page used in this example, the navigation is done using Page.getCurrent().setUriFragment("!"+OtherSecurePage.NAME); that change the uri fragment as before.

Logout button

		logout = new Button("Logout");
		logout.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				getUI().getNavigator().removeView(SecurePage.NAME);
				getUI().getNavigator().removeView(OtherSecurePage.NAME);
				VaadinSession.getCurrent().setAttribute("user", null);
				Page.getCurrent().setUriFragment("");
			}
		});

The logout button first remove the secure page view with getUI().getNavigator().removeView(SecurePage.NAME);, remove the other secure page with getUI().getNavigator().removeView(OtherSecurePage.NAME);, clean the session with VaadinSession.getCurrent().setAttribute("user", null); and clean the uri fragment to change the current page to the login page, removing the views prevent it to be accessible from the navigator.

Place the components

		secure = new Label("secure");
		currentUser = new Label("Current User");
		addComponent(secure);
		addComponent(currentUser);
		addComponent(otherSecure);
		addComponent(logout);

Add the components to the layout to show them.

enter

	@Override
	public void enter(ViewChangeEvent event) {
		currentUser.setCaption("Current user : " + VaadinSession.getCurrent().getAttribute("user").toString()); 

	}

This event is always called before the view is shown to the screen, here I get the username from the session and show it in the currentUser label.

5.4 OtherSecure page

OtherSecure page

public class OtherSecurePage extends VerticalLayout implements View{

	private static final long serialVersionUID = 1L;
	private Label otherSecure;
	public static final String NAME = "OtherSecure";
	private Button mainsecure;

	public OtherSecurePage() {
		mainsecure = new Button("Main Secure Area");
		mainsecure.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				Page.getCurrent().setUriFragment("!"+SecurePage.NAME);
			}
		});
		otherSecure = new Label("Other Secure Page ...");
		addComponent(otherSecure);
		addComponent(mainsecure);
	}
	@Override
	public void enter(ViewChangeEvent event) {
		
	}

}

This page only have one button that send the user to the secure page, is made here to the purpose of show how to handle multiples pages inside the secure area, usually is a better idea to make a navigation menu and inside the navigation menu put all your pages, to avoid make a navigation widget for every page but everything here depends on your design, remember if the design is bad the rest is bad too so a solid rock design is the bullet proof foundation of your program.

5.5 The main UI

Init

	public static Authentication AUTH;
	@Override
	protected void init(VaadinRequest request) {
		AUTH = new Authentication();
		new Navigator(this, this);

Ok here I declared an static AUTH variable to store an instance of the Authentication class and create a Navigator(this, this), the navigator is a class that tracks the active view using URI fragments, is in charge of show the current view and store a record and change the other views.

Initial page

		getNavigator().addView(LoginPage.NAME, LoginPage.class);
		getNavigator().setErrorView(LoginPage.class);

Using the navigator, add the login page as a view and set the error page, the error view is a page that is redirected when an error occurs in the application. In this case I used the same login page as an error view, just to no create another dummy page and the login page is public and if any error raise in the application I don’t want a user hanging in the private area, the error page is a design topic, where you need it and how.

Uri fragment listener

		Page.getCurrent().addUriFragmentChangedListener(new UriFragmentChangedListener() {
			
			@Override
			public void uriFragmentChanged(UriFragmentChangedEvent event) {
				router(event.getUriFragment());
			}
		});
		router("");

To know when the uri fragment changes we have this listener so every time the uri fragment is modified the router function is called with the new uri fragment as a parameter, and finally I call the router with a empty string to redirect the page to the login page.

router method

	private void router(String route){
		Notification.show(route);
		if(getSession().getAttribute("user") != null){
			getNavigator().addView(SecurePage.NAME, SecurePage.class);
			getNavigator().addView(OtherSecurePage.NAME, OtherSecurePage.class);
			if(route.equals("!OtherSecure")){
				getNavigator().navigateTo(OtherSecurePage.NAME);
			}else{
				getNavigator().navigateTo(SecurePage.NAME);
			}
		}else{
			getNavigator().navigateTo(LoginPage.NAME);
		}
	}

This router method is in charge of the page flow. Every time the uri changes the application call this method and using the navigator change the page to the correct one. If the user is no logged and try to navigate to an in-existent page this router shows the login page and in the case the user is logged in the the router navigate to the secure page by default, so it checks the session with if(getSession().getAttribute("user") != null). If no user is in the session then show the login page and if the user is in the session navigate to the secure area, this can be done because the session is stored server side and because you are handling the user in the server is safe to navigate in this way. You can use cookies for user authentication too but is not recommended because cookies are stored client side and can be forged by malicious users.

6. The complete source code

VaadinloginUI.java

package com.example.vaadinlogin;

import javax.servlet.annotation.WebServlet;

import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.navigator.Navigator;
import com.vaadin.server.Page;
import com.vaadin.server.Page.UriFragmentChangedEvent;
import com.vaadin.server.Page.UriFragmentChangedListener;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.Notification;
import com.vaadin.ui.UI;

@SuppressWarnings("serial")
@Theme("vaadinlogin")
public class VaadinloginUI extends UI {

	@WebServlet(value = "/*", asyncSupported = true)
	@VaadinServletConfiguration(productionMode = false, ui = VaadinloginUI.class)
	public static class Servlet extends VaadinServlet {
	}

	public static Authentication AUTH;
	@Override
	protected void init(VaadinRequest request) {
		AUTH = new Authentication();
		new Navigator(this, this);
		
		getNavigator().addView(LoginPage.NAME, LoginPage.class);
		getNavigator().setErrorView(LoginPage.class);
		
		Page.getCurrent().addUriFragmentChangedListener(new UriFragmentChangedListener() {
			
			@Override
			public void uriFragmentChanged(UriFragmentChangedEvent event) {
				router(event.getUriFragment());
			}
		});
		
		
		router("");
	}
	
	private void router(String route){
		Notification.show(route);
		if(getSession().getAttribute("user") != null){
			getNavigator().addView(SecurePage.NAME, SecurePage.class);
			getNavigator().addView(OtherSecurePage.NAME, OtherSecurePage.class);
			if(route.equals("!OtherSecure")){
				getNavigator().navigateTo(OtherSecurePage.NAME);
			}else{
				getNavigator().navigateTo(SecurePage.NAME);
			}
		}else{
			getNavigator().navigateTo(LoginPage.NAME);
		}
	}

}

LoginPage.java

package com.example.vaadinlogin;

import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.server.Page;
import com.vaadin.server.VaadinSession;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Panel;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;

public class LoginPage extends VerticalLayout implements View {
	private static final long serialVersionUID = 1L;
	public static final String NAME = "";

	public LoginPage(){
		Panel panel = new Panel("Login");
		panel.setSizeUndefined();
		addComponent(panel);

		
		FormLayout content = new FormLayout();
		TextField username = new TextField("Username");
		content.addComponent(username);
		PasswordField password = new PasswordField("Password");
		content.addComponent(password);

		Button send = new Button("Enter");
		send.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				if(VaadinloginUI.AUTH.authenticate(username.getValue(), password.getValue())){
					VaadinSession.getCurrent().setAttribute("user", username.getValue());
					getUI().getNavigator().addView(SecurePage.NAME, SecurePage.class);
					getUI().getNavigator().addView(OtherSecurePage.NAME, OtherSecurePage.class);
					Page.getCurrent().setUriFragment("!"+SecurePage.NAME);
				}else{
					Notification.show("Invalid credentials", Notification.Type.ERROR_MESSAGE);
				}
			}
			
		});
		content.addComponent(send);
		content.setSizeUndefined();
		content.setMargin(true);
		panel.setContent(content);
		setComponentAlignment(panel, Alignment.MIDDLE_CENTER);
	
	}
	
	@Override
	public void enter(ViewChangeEvent event) {
		
	}

}

SecurePage.java

package com.example.vaadinlogin;

import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.server.Page;
import com.vaadin.server.VaadinSession;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Label;
import com.vaadin.ui.VerticalLayout;

public class SecurePage extends VerticalLayout implements View {
	private static final long serialVersionUID = 1L;
	private Label secure;
	private Label currentUser;
	private Button otherSecure;
	private Button logout;
	public static final String NAME = "Secure";

	public SecurePage() {
		
		otherSecure = new Button("OtherSecure");
		otherSecure.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				Page.getCurrent().setUriFragment("!"+OtherSecurePage.NAME);
			}
		});
		
		logout = new Button("Logout");
		logout.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				getUI().getNavigator().removeView(SecurePage.NAME);
				getUI().getNavigator().removeView(OtherSecurePage.NAME);
				VaadinSession.getCurrent().setAttribute("user", null);
				Page.getCurrent().setUriFragment("");
			}
		});
		
		secure = new Label("secure");
		currentUser = new Label("Current User");
		addComponent(secure);
		addComponent(currentUser);
		addComponent(otherSecure);
		addComponent(logout);
	}

	@Override
	public void enter(ViewChangeEvent event) {
		currentUser.setCaption("Current user : " + VaadinSession.getCurrent().getAttribute("user").toString()); 

	}

}

OtherSecurePage.java

package com.example.vaadinlogin;

import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.server.Page;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;

public class OtherSecurePage extends VerticalLayout implements View{

	private static final long serialVersionUID = 1L;
	private Label otherSecure;
	public static final String NAME = "OtherSecure";
	private Button mainsecure;

	public OtherSecurePage() {
		mainsecure = new Button("Main Secure Area");
		mainsecure.addClickListener(new ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				Page.getCurrent().setUriFragment("!"+SecurePage.NAME);
			}
		});
		otherSecure = new Label("Other Secure Page ...");
		addComponent(otherSecure);
		addComponent(mainsecure);
	}
	@Override
	public void enter(ViewChangeEvent event) {
		
	}

}

Authentication.java

package com.example.vaadinlogin;

public class Authentication {
	
	private String username;
	private String password;
	
	public Authentication() {
		setUsername("myuser");
		setPassword("mypass");
	}

	private void setUsername(String username) {
		this.username = username;
	}
	
	private String getUsername(){
		return this.username;
	}

	private void setPassword(String password) {
		this.password = password;
	}
	
	private String getPassword(){
		return this.password;
	}
	
	public Boolean authenticate(String username, String password){
		if(username.equals(getUsername()) && password.equals(getPassword())){
			return true;
		}
		return false;
	}

}

7. Running the example

Right click on the project folder and choose Run as -> Run on server choose Tomcat 8 server and hit finish.

8. Results

Failed Login:

03 Login Form Failed Login
03 Login Form Failed Login

Filled Login:

04 Login Form Filled
04 Login Form Filled

Secure Page:

05 Secure Page
05 Secure Page

The Other Secure Page:

06 Other Secure Page
06 Other Secure Page

9. Download the Source Code

This was an example of Vaadin Login.

Download
You can download the Eclipse project here: VaadinLogin

Jesus Boadas

I'm a self taught programmer, I began programming back in 1991 using an IBM A10 mainframe with Pascal an Assembler IBM 360/70 emulator and Turbo C on a X86 PC, since that I work for the banking industry with emerging technologies like Fox Pro, Visual Fox Pro, Visual Basic, Visual C++, Borland C++, lately I moved out to the Airline industry, leading designing and programming in-house web applications with Flex, Actionscript, PHP, Python and Rails and in the last 7 years I focused all my work in Java, working on Linux servers using GlassFish, TomCat, Apache and MySql.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Zoltan Korponai
Zoltan Korponai
6 years ago

Hello,
I tried this example because it’s understandable and transparent to me. (I’m beginner in Java). And it’s worked fine. So I want to improve it and combined it with Spring boot. The Authentication class is directly injected into the LoginPage class. But it does not work. It throws a NullPointerException. The final goal is its use with JPA.
I upload my code to GitHub here: https://github.com/korponaiz/test-vaadin-spring-login

Back to top button