001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.authroles.authentication.panel; 018 019import org.apache.wicket.RestartResponseException; 020import org.apache.wicket.authentication.IAuthenticationStrategy; 021import org.apache.wicket.authentication.strategy.DefaultAuthenticationStrategy; 022import org.apache.wicket.authroles.authentication.AuthenticatedWebSession; 023import org.apache.wicket.markup.html.WebMarkupContainer; 024import org.apache.wicket.markup.html.form.CheckBox; 025import org.apache.wicket.markup.html.form.PasswordTextField; 026import org.apache.wicket.markup.html.form.StatelessForm; 027import org.apache.wicket.markup.html.form.TextField; 028import org.apache.wicket.markup.html.panel.FeedbackPanel; 029import org.apache.wicket.markup.html.panel.Panel; 030import org.apache.wicket.model.CompoundPropertyModel; 031 032/** 033 * Reusable user sign in panel with username and password as well as support for persistence of the 034 * both. When the SignInPanel's form is submitted, the method signIn(String, String) is called, 035 * passing the username and password submitted. The signIn() method should authenticate the user's 036 * session. 037 * 038 * @see IAuthenticationStrategy 039 * @see org.apache.wicket.settings.SecuritySettings#getAuthenticationStrategy() 040 * @see DefaultAuthenticationStrategy 041 * 042 * @author Jonathan Locke 043 * @author Juergen Donnerstag 044 * @author Eelco Hillenius 045 */ 046public class SignInPanel extends Panel 047{ 048 private static final long serialVersionUID = 1L; 049 050 private static final String SIGN_IN_FORM = "signInForm"; 051 052 /** True if the panel should display a remember-me checkbox */ 053 private boolean includeRememberMe = true; 054 055 /** True if the user should be remembered via form persistence (cookies) */ 056 private boolean rememberMe = true; 057 058 /** password. */ 059 private String password; 060 061 /** user name. */ 062 private String username; 063 064 /** 065 * @see org.apache.wicket.Component#Component(String) 066 */ 067 public SignInPanel(final String id) 068 { 069 this(id, true); 070 } 071 072 /** 073 * @param id 074 * See Component constructor 075 * @param includeRememberMe 076 * True if form should include a remember-me checkbox 077 * @see org.apache.wicket.Component#Component(String) 078 */ 079 public SignInPanel(final String id, final boolean includeRememberMe) 080 { 081 super(id); 082 083 this.includeRememberMe = includeRememberMe; 084 085 // Create feedback panel and add to page 086 add(new FeedbackPanel("feedback")); 087 088 // Add sign-in form to page, passing feedback panel as 089 // validation error handler 090 add(new SignInForm(SIGN_IN_FORM)); 091 } 092 093 /** 094 * 095 * @return signin form 096 */ 097 protected SignInForm getForm() 098 { 099 return (SignInForm)get(SIGN_IN_FORM); 100 } 101 102 /** 103 * Try to sign-in with remembered credentials. 104 * 105 * @see #setRememberMe(boolean) 106 */ 107 @Override 108 protected void onConfigure() 109 { 110 // logged in already? 111 if (isSignedIn() == false) 112 { 113 IAuthenticationStrategy authenticationStrategy = getApplication().getSecuritySettings() 114 .getAuthenticationStrategy(); 115 // get username and password from persistence store 116 String[] data = authenticationStrategy.load(); 117 118 if ((data != null) && (data.length > 1)) 119 { 120 // try to sign in the user 121 if (signIn(data[0], data[1])) 122 { 123 username = data[0]; 124 password = data[1]; 125 126 onSignInRemembered(); 127 } 128 else 129 { 130 // the loaded credentials are wrong. erase them. 131 authenticationStrategy.remove(); 132 } 133 } 134 } 135 136 super.onConfigure(); 137 } 138 139 /** 140 * Convenience method to access the password. 141 * 142 * @return The password 143 */ 144 public String getPassword() 145 { 146 return password; 147 } 148 149 /** 150 * Set the password 151 * 152 * @param password 153 */ 154 public void setPassword(final String password) 155 { 156 this.password = password; 157 } 158 159 /** 160 * Convenience method to access the username. 161 * 162 * @return The user name 163 */ 164 public String getUsername() 165 { 166 return username; 167 } 168 169 /** 170 * Set the username 171 * 172 * @param username 173 */ 174 public void setUsername(final String username) 175 { 176 this.username = username; 177 } 178 179 /** 180 * Get model object of the rememberMe checkbox 181 * 182 * @return True if user should be remembered in the future 183 */ 184 public boolean getRememberMe() 185 { 186 return rememberMe; 187 } 188 189 /** 190 * @param rememberMe 191 * If true, rememberMe will be enabled (username and password will be persisted 192 * somewhere) 193 */ 194 public void setRememberMe(final boolean rememberMe) 195 { 196 this.rememberMe = rememberMe; 197 } 198 199 /** 200 * Sign in user if possible. 201 * 202 * @param username 203 * The username 204 * @param password 205 * The password 206 * @return True if signin was successful 207 */ 208 private boolean signIn(String username, String password) 209 { 210 return AuthenticatedWebSession.get().signIn(username, password); 211 } 212 213 /** 214 * @return true, if signed in 215 */ 216 private boolean isSignedIn() 217 { 218 return AuthenticatedWebSession.get().isSignedIn(); 219 } 220 221 /** 222 * Called when sign in failed 223 */ 224 protected void onSignInFailed() 225 { 226 // Try the component based localizer first. If not found try the 227 // application localizer. Else use the default 228 error(getLocalizer().getString("signInFailed", this, "Sign in failed")); 229 } 230 231 /** 232 * Called when sign in was successful 233 */ 234 protected void onSignInSucceeded() 235 { 236 // If login has been called because the user was not yet logged in, than continue to the 237 // original destination, otherwise to the Home page 238 continueToOriginalDestination(); 239 setResponsePage(getApplication().getHomePage()); 240 } 241 242 /** 243 * Called when sign-in was remembered. 244 * <p> 245 * By default tries to continue to the original destination or switches to the application's 246 * home page. 247 * <p> 248 * Note: This method will be called during rendering of this panel, thus a 249 * {@link RestartResponseException} has to be used to switch to a different page. 250 * 251 * @see #onConfigure() 252 */ 253 protected void onSignInRemembered() 254 { 255 // logon successful. Continue to the original destination 256 continueToOriginalDestination(); 257 258 // Ups, no original destination. Go to the home page 259 throw new RestartResponseException(getApplication().getHomePage()); 260 } 261 262 /** 263 * Sign in form. 264 */ 265 public final class SignInForm extends StatelessForm<SignInPanel> 266 { 267 private static final long serialVersionUID = 1L; 268 269 /** 270 * Constructor. 271 * 272 * @param id 273 * id of the form component 274 */ 275 public SignInForm(final String id) 276 { 277 super(id); 278 279 setModel(new CompoundPropertyModel<>(SignInPanel.this)); 280 281 // Attach textfields for username and password 282 add(new TextField<>("username").setRequired(true)); 283 add(new PasswordTextField("password")); 284 285 // container for remember me checkbox 286 WebMarkupContainer rememberMeContainer = new WebMarkupContainer("rememberMeContainer"); 287 add(rememberMeContainer); 288 289 // Add rememberMe checkbox 290 rememberMeContainer.add(new CheckBox("rememberMe")); 291 292 // Show remember me checkbox? 293 rememberMeContainer.setVisible(includeRememberMe); 294 } 295 296 @Override 297 public void onSubmit() 298 { 299 IAuthenticationStrategy strategy = getApplication().getSecuritySettings() 300 .getAuthenticationStrategy(); 301 302 if (signIn(getUsername(), getPassword())) 303 { 304 if (rememberMe == true) 305 { 306 strategy.save(username, password); 307 } 308 else 309 { 310 strategy.remove(); 311 } 312 313 onSignInSucceeded(); 314 } 315 else 316 { 317 onSignInFailed(); 318 strategy.remove(); 319 } 320 } 321 } 322}