/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.server.headlessclient; import org.apache.wicket.RequestCycle; import org.apache.wicket.Session; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.PasswordTextField; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.form.persistence.CookieValuePersister; import org.apache.wicket.markup.html.form.persistence.CookieValuePersisterSettings; import org.apache.wicket.markup.html.form.persistence.IValuePersister; import org.apache.wicket.markup.html.panel.FeedbackPanel; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.protocol.http.WebRequestCycle; import org.apache.wicket.util.value.ValueMap; import com.servoy.j2db.util.Debug; import com.servoy.j2db.util.SecuritySupport; import com.servoy.j2db.util.Settings; public class SignIn extends WebPage { /** True if the panel should display a remember-me checkbox */ private static final boolean includeRememberMe = true; /** Field for password. */ private PasswordTextField password; /** True if the user should be remembered via form persistence (cookies) */ private boolean rememberMe = true; /** Field for user name. */ private TextField username; /** * @param id See Component constructor * @param includeRememberMe True if form should include a remember-me checkbox * @see wicket.Component#Component(String) */ public SignIn() { // Create feedback panel and add to page FeedbackPanel feedback = new FeedbackPanel("feedback"); add(feedback); // Add sign-in form to page, passing feedback panel as // validation error handler SignInForm signInForm = new SignInForm("signInForm"); add(signInForm); signInForm.loadPersistentFormComponentValues(); String usr = username.getDefaultModelObjectAsString(); String pwd = password.getDefaultModelObjectAsString(); if (usr != "" && usr != null && pwd != "" && pwd != null) { if (signIn(usr, pwd)) { if (!getPage().continueToOriginalDestination()) { setResponsePage(Session.get().getPageFactory().newPage(getApplication().getHomePage(), null)); } } } } /** * Sign in form. */ public final class SignInForm extends Form { private static final String PROPERTY_USERNAME = "username"; //$NON-NLS-1$ private static final String PROPERTY_PASSWORD = "password"; //$NON-NLS-1$ private static final String PROPERTY_REMEMBER_ME = "rememberMe"; //$NON-NLS-1$ private String cookieKeyPassword; /** El-cheapo model for form. */ private final ValueMap properties = new ValueMap(); /** * Constructor. * * @param id id of the form component * @param feedback The feedback panel to update */ public SignInForm(final String id) { super(id); cookieKeyPassword = id + ':' + PROPERTY_PASSWORD; // Attach textfield components that edit properties map // in lieu of a formal beans model add(username = new TextField(PROPERTY_USERNAME, new PropertyModel(properties, PROPERTY_USERNAME), String.class)); add(password = new PasswordTextField(PROPERTY_PASSWORD, new PropertyModel(properties, PROPERTY_PASSWORD)) { private static final long serialVersionUID = 1L; @Override protected boolean supportsPersistence() { return true; } }); password.setType(String.class); // MarkupContainer row for remember me checkbox WebMarkupContainer rememberMeRow = new WebMarkupContainer("rememberMeRow"); add(rememberMeRow); // Add rememberMe checkbox rememberMeRow.add(new CheckBox(PROPERTY_REMEMBER_ME, new PropertyModel(SignIn.this, PROPERTY_REMEMBER_ME))); // Make form values persistent setPersistent(rememberMe); // Show remember me checkbox? rememberMeRow.setVisible(includeRememberMe); } /** * @see wicket.markup.html.form.Form#onSubmit() */ @Override public final void onSubmit() { if (signIn(username.getDefaultModelObjectAsString(), password.getDefaultModelObjectAsString())) { // If login has been called because the user was not yet // logged in, then continue to the original destination, // otherwise to the Home page if (!getPage().continueToOriginalDestination()) { setResponsePage(Session.get().getPageFactory().newPage(getApplication().getHomePage(), null)); } } else { // Try the component based localizer first. If not found try the // application localizer. Else use the default final String errmsg = getLocalizer().getString("loginError", this, "Unable to sign you in"); //$NON-NLS-1$ //$NON-NLS-2$ error(errmsg); } } @Override protected IValuePersister getValuePersister() { // use secure cookies for persistent fields CookieValuePersisterSettings settings = new CookieValuePersisterSettings(); settings.setSecure(Boolean.parseBoolean(Settings.getInstance().getProperty("servoy.webclient.enforceSecureCookies", "false")) || ((WebRequestCycle)RequestCycle.get()).getWebRequest().getHttpServletRequest().isSecure()); return new CookieValuePersister(settings) { @Override public String load(final String key) { String cookieValue = super.load(key); if (cookieKeyPassword.equals(key)) { try { cookieValue = SecuritySupport.decrypt(Settings.getInstance(), cookieValue); } catch (Exception ex) { Debug.error("Cannot decrypt password when loading it from a cookie", ex); cookieValue = null; } } return cookieValue; } @Override public void save(String key, final String value) { String cookieValue = value; if (cookieKeyPassword.equals(key)) { try { cookieValue = SecuritySupport.encrypt(Settings.getInstance(), cookieValue); super.save(key, cookieValue); } catch (Exception ex) { Debug.error("Cannot encrypt password when saving it into a cookie", ex); } } else super.save(key, cookieValue); } }; } } /** * Convenience method set persistence for username and password. * * @param enable Whether the fields should be persistent */ private void setPersistent(boolean enable) { username.setPersistent(enable); password.setPersistent(enable); if (!enable) { // Remove persisted user data. Search for child component // of type SignInForm and remove its related persistence values. getPage().removePersistedFormData(SignInForm.class, true); } } /** * Get model object of the rememberMe checkbox * * @return True if user should be remembered in the future */ public boolean getRememberMe() { return rememberMe; } /** * Set model object for rememberMe checkbox */ public void setRememberMe(boolean rememberMe) { this.rememberMe = rememberMe; this.setPersistent(rememberMe); } /** * Sign in user if possible. * * @param username The username * @param password The password * @return True if signin was successful */ private boolean signIn(final String username, final String password) { return ((WebClientSession)getSession()).authenticate(username, password); } }