I have an old web application which I need to migrate to Vaadin.
In the old app there is a page which asks the user for login and password.
The JSP page looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8"%>
[...]
<head>
<title>Some product</title>
<link rel="stylesheet" type="text/css" href="<%=request.getContextPath()+"/css/styles.css"%>" />
</head>
<body>
<%@ include file="inc/main-navigation.jsp"%>
<form action="j_security_check" method="post" style="margin:0px">
[...]
<input type="text" style="width:100%" name="j_username" />
<input type="password" name="j_password" />
</form>
</body>
</html>
web.xml
contains following entries:
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Some product</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login_fail.jsp</form-error-page>
</form-login-config>
</login-config>
This means that in case of unsuccessful authentication the user is directed to page login_fail.jsp
.
In the context.xml
file I found following entry from which I conclude that there is an internal mechanism in Tomcat which reads correct login and password from the specified database and performs their check without any additional code.
<Context path="/myapp">
<Realm className="org.apache.catalina.realm.JDBCRealm" driverName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
connectionURL="[...]"
userTable="[...]" userNameCol="user_name" userCredCol="user_pass"
userRoleTable="[...]" roleNameCol="role_name"/>
</Context>
In the Vaadin application I have a UI with both text fields and a button.
public class BookkeepingView extends VerticalLayout implements View {
public BookkeepingView()
{
VerticalLayout contentPanel = new VerticalLayout();
contentPanel.setStyleName("body");
contentPanel.addComponent(getHeaderPanel());
contentPanel.addComponent(getLoginPanel());
contentPanel.addComponent(getFooterPanel());
addComponent(contentPanel);
}
private Component getHeaderPanel() {
return createCustomLayoutPanel("main-navigation");
}
private Component getFooterPanel() {
return createCustomLayoutPanel("copyright");
}
private CustomLayout getLoginPanel() {
Panel panel = new Panel();
panel.setSizeUndefined();
addComponent(panel);
CustomLayout customLayoutPanel = new CustomLayout("login");
final TextField userName = new TextField();
customLayoutPanel.addComponent(userName, "j_username");
final PasswordField password = new PasswordField();
customLayoutPanel.addComponent(password, "j_password");
final Button loginButton = new Button(I18n.l("bookkeeping_login_button"));
customLayoutPanel.addComponent(loginButton, "login");
loginButton.addClickListener(new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent clickEvent) {
loginButtonPressed();
}
});
return customLayoutPanel;
}
private void loginButtonPressed() {
Notification.show("Login button pressed", Notification.Type.TRAY_NOTIFICATION);
}
private CustomLayout createCustomLayoutPanel(final String aHtmlFileName) {
Panel panel = new Panel();
panel.setSizeUndefined();
addComponent(panel);
CustomLayout customLayoutPanel = new CustomLayout(aHtmlFileName);
return customLayoutPanel;
}
@Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
}
}
When the user presses the button (method loginButtonPressed
is executed), I want to
userName
and password
,How can I make my Vaadin application access that Tomcat mechanism for checking the credentials (i. e. my Vaadin application should perform the credentials check in exactly the same way as the old app)?
What code allows me to check whether user name x
and password y
are valid according to database specified in context.xml
?
Update 1 (05.11.2013): I found a description of how to use realm-based authentication here.
But I ran into a problem:
The application servlet in the example extends com.vaadin.terminal.gwt.server.AbstractApplicationServlet
, which is not available in my Vaadin 7 project.
@WebServlet(urlPatterns={"/ui/*", "/VAADIN/*"})
public class DemoAppServlet extends AbstractApplicationServlet {
Update 2 (05.11.2013 15:53):
I tried to implement authentication in the simplest possible way:
1) Use BASIC authentication mechanism. 2) Configure the web app so that all Vaadin pages require the user to be logged in.
In order to achieve this, I added following fragments to web.xml
:
<servlet-mapping>
<servlet-name>VaadinDemoApp</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<security-constraint>
<display-name>VaadinDemoApplicationConstraint</display-name>
<web-resource-collection>
<web-resource-name>Vaadin application</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
<role-name>viewer</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Protected page</realm-name>
</login-config>
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>viewer</role-name>
</security-role>
But it doesn't work: The credentials dialog box is displayed upon access to the application, but when I enter correct credentials and press "OK", the same dialog box appears again.
It seems like you have overcomplicated everything. Please find below real-life solution. It is used for a Vaadin application and simply works.
1. You need external login page
This is the simplest way. If you want, you can easily style that page in order not to break user experience.
<link rel="stylesheet" type="text/css" href="VAADIN/themes/reindeer/styles.css">
...
<div class="v-app v-theme-reindeer">
As usual you will have the following:
<form id="login" method="post" action="j_security_check" >
<input name="j_username" type="text">
<input name="j_password" type="text">
2. I would suggest to have external login failed page
Basically it just needs to notify a user there was something wrong. It might also suggest, for example, to relogin.
3. Configure proper auth method
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/VAADIN/loginPage.html</form-login-page>
<form-error-page>/VAADIN/loginFailed.html</form-error-page>
</form-login-config>
</login-config>
4. Do not forget to set session timeout
<session-config>
<session-timeout>60</session-timeout>
</session-config>
5. You are done, just test