So, you want to enable in your vaadin app automated authentification based on request params. The right location for this functionality is your instance of com.vaadin.ui.UI class — here the decision is made which view to show. If the provided for authentification data is incorrect or incomplete, then we will show login view. If the authentification was successful, we show some other view. There are means to pass params between the views, I will mention them later in this article. But they don’t work for authentification.
Sending pass as plain text is a bad practice, you may think of using encrypted password (still can be seen in the browser’s history) or one-time tokens (no need to send the login then). I used login and password params just for demo purpose.
The needed data on requested URL — the first one to ypur app from the current browser’s tab — can be extracted from VaadinRequest in the method init(VaadinRequest vaadinRequest). I used some debug logging:
Map<String ,String[]> paramMap = vaadinRequest.getParameterMap(); for (Map.Entry<String ,String[]> entry: paramMap.entrySet()){ LOG.debug(">>>> " + entry.getKey() ); for (String param: entry.getValue()){ LOG.debug("< <<< " + param); } } |
You are supposed to see output like this:
2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-1475658135205 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-browserDetails 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 1 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> theme 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< valo 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-appId 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< main-3343801 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-sh 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 864 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-sw 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 1536 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-cw 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 1423 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-ch 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 771 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-curdate 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 1475658135206 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-tzo 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< -180 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-dstd 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 0 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-rtzo 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< -180 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-dston 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< false 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-vw 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 1423 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-vh 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< 0 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-loc 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< http://localhost:8080/main/#!login/log=2222&pass=3333 2016-10-05 12:02:15 DEBUG PostOfficeUI:33 - >>>> v-wn 2016-10-05 12:02:15 DEBUG PostOfficeUI:35 - < <<< main-3343801-0.0269370820741045 |
By using «=» and «&» we make links more HTTP-friendly.
Now it’s clear we need the array for key «v-loc»:
private static final String REQUESTED_URL_KEY = "v-loc"; private static final String DELIMITER = "&"; private static final String EQUALITY_SIGN = "="; private static final String LOGIN_KEYWORD = "login"; private static final String PASSWORD_KEYWORD = "pass"; String[] urls = paramMap.get(REQUESTED_URL_KEY); String url = urls[0]; |
We want to parse the link, param part is after the last slash — «log=2222&pass=3333»:
String paramString = url.substring(url.lastIndexOf("/") + 1); |
Please note that we don’t check the name of the requested view currently.
If there were no param part like in the link http://localhost:8080/main/#!login , after the last slash we get «#!login» and can exit early:
Map<String , String> argMap = new HashMap<>(); if (StringUtils.isBlank(paramString) || paramString.contains("#!")) { // there were no part with params return argMap; } |
Now populate the arg map:
String[] msgs = paramString.split(DELIMITER); for (String msg : msgs) { // now splitting each part and adding parts key=value into a HashMap<> String[] params = msg.split(EQUALITY_SIGN); if (params.length == 2 && StringUtils.isNotBlank(params[0]) && StringUtils.isNotBlank(params[0])){ argMap.put(params[0], params[1]); } } |
We can use string values argMap.get(LOGIN_KEYWORD) and argMap.get(PASSWORD_KEYWORD) in our auth service:
if (authenticationService.authenticate(login, pass)) { Employee employee = employeeService.findByLogin(login); // todo compare passwords if (employee != null) { container.setEmployee(employee); authIsSuccessful = true; } } Navigator navigator = new Navigator(this, this); navigator.addProvider(viewProvider); if (authIsSuccessful) { navigator.navigateTo(OfficeView.VIEW_NAME); } else { navigator.navigateTo(LoginView.VIEW_NAME); } |
That’s it!
And now about sending parameters between views. Our com.vaadin.navigator.View has method enter(ViewChangeListener.ViewChangeEvent viewChangeEvent). Params can be retrieved as follows:
if(viewChangeEvent.getParameters() != null) { Map<String , String> paramMap = new HashMap<>(3); String[] msgs = viewChangeEvent.getParameters().split(DELIMITER); for (String msg : msgs) { // now splitting each part and adding parts key=value into a HashMap<> String[] params = msg.split(EQUALITY_SIGN); if (params.length == 2 && StringUtils.isNotBlank(params[0]) && StringUtils.isNotBlank(params[0])){ paramMap.put(params[0], params[1]); } } ... } |
You can react upon the values in paramMap now, for eample update the data on the view.
Update. Some details on how vaadin gets param v-loc. I’ve captured traffic with wireshark and in the sequence of requests found this POST:
/app/main/?v-1490967795580 HTTP/1.1 Accept: / Content-Type: application/x-www-form-urlencoded Referer: http://localhost:8080/app/main/ Accept-Language: ru-RU Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible;) Host: localhost:8080 Content-Length: 304 Connection: Keep-Alive Cache-Control: no-cache Cookie: JSESSIONID=BFEF3F7019FE938BAE24327AC754A59E v-browserDetails=1&theme=mytheme&v-appId=appmain-1967030724 &v-sh=768&v-sw=1366&v-cw=1366&v-ch=706&v-curdate=1490967795638 &v-tzo=-180&v-dstd=0&v-rtzo=-180&v-dston=false&v-vw=1366&v-vh=706& v-loc=http%3A%2F%2Flocalhost%3A8080%2Fabon-client%2Fmain%2F &v-wn=appmain-1967030724-0.9856022015215805 |
This request is initiated by vaadin itself. You can see our param in the body of this request.