1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 package org.apache.shiro.authc; 20 21 /** 22 * <p>A simple username/password authentication token to support the most widely-used authentication mechanism. This 23 * class also implements the {@link RememberMeAuthenticationToken RememberMeAuthenticationToken} interface to support 24 * "Remember Me" services across user sessions as well as the 25 * {@link org.apache.shiro.authc.HostAuthenticationToken HostAuthenticationToken} interface to retain the host name 26 * or IP address location from where the authentication attempt is occurring.</p> 27 * <p/> 28 * <p>"Remember Me" authentications are disabled by default, but if the application developer wishes to allow 29 * it for a login attempt, all that is necessary is to call {@link #setRememberMe setRememberMe(true)}. If the underlying 30 * <tt>SecurityManager</tt> implementation also supports <tt>RememberMe</tt> services, the user's identity will be 31 * remembered across sessions. 32 * <p/> 33 * <p>Note that this class stores a password as a char[] instead of a String 34 * (which may seem more logical). This is because Strings are immutable and their 35 * internal value cannot be overwritten - meaning even a nulled String instance might be accessible in memory at a later 36 * time (e.g. memory dump). This is not good for sensitive information such as passwords. For more information, see the 37 * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/security/jce/JCERefGuide.html#PBEEx"> 38 * Java Cryptography Extension Reference Guide</a>.</p> 39 * <p/> 40 * <p>To avoid this possibility of later memory access, the application developer should always call 41 * {@link #clear() clear()} after using the token to perform a login attempt.</p> 42 * 43 * @since 0.1 44 */ 45 public class UsernamePasswordToken implements HostAuthenticationToken, RememberMeAuthenticationToken { 46 47 /*-------------------------------------------- 48 | C O N S T A N T S | 49 ============================================*/ 50 51 /*-------------------------------------------- 52 | I N S T A N C E V A R I A B L E S | 53 ============================================*/ 54 /** 55 * The username 56 */ 57 private String username; 58 59 /** 60 * The password, in char[] format 61 */ 62 private char[] password; 63 64 /** 65 * Whether or not 'rememberMe' should be enabled for the corresponding login attempt; 66 * default is <code>false</code> 67 */ 68 private boolean rememberMe; 69 70 /** 71 * The location from where the login attempt occurs, or <code>null</code> if not known or explicitly 72 * omitted. 73 */ 74 private String host; 75 76 /*-------------------------------------------- 77 | C O N S T R U C T O R S | 78 ============================================*/ 79 80 /** 81 * JavaBeans compatible no-arg constructor. 82 */ 83 public UsernamePasswordToken() { 84 } 85 86 /** 87 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted 88 * during an authentication attempt, with a <tt>null</tt> {@link #getHost() host} and a 89 * <tt>rememberMe</tt> default of <tt>false</tt>. 90 * 91 * @param username the username submitted for authentication 92 * @param password the password character array submitted for authentication 93 */ 94 public UsernamePasswordToken(final String username, final char[] password) { 95 this(username, password, false, null); 96 } 97 98 /** 99 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted 100 * during an authentication attempt, with a <tt>null</tt> {@link #getHost() host} and 101 * a <tt>rememberMe</tt> default of <tt>false</tt> 102 * <p/> 103 * <p>This is a convenience constructor and maintains the password internally via a character 104 * array, i.e. <tt>password.toCharArray();</tt>. Note that storing a password as a String 105 * in your code could have possible security implications as noted in the class JavaDoc.</p> 106 * 107 * @param username the username submitted for authentication 108 * @param password the password string submitted for authentication 109 */ 110 public UsernamePasswordToken(final String username, final String password) { 111 this(username, password != null ? password.toCharArray() : null, false, null); 112 } 113 114 /** 115 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted, the 116 * inetAddress from where the attempt is occurring, and a default <tt>rememberMe</tt> value of <tt>false</tt> 117 * 118 * @param username the username submitted for authentication 119 * @param password the password string submitted for authentication 120 * @param host the host name or IP string from where the attempt is occurring 121 * @since 0.2 122 */ 123 public UsernamePasswordToken(final String username, final char[] password, final String host) { 124 this(username, password, false, host); 125 } 126 127 /** 128 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted, the 129 * inetAddress from where the attempt is occurring, and a default <tt>rememberMe</tt> value of <tt>false</tt> 130 * <p/> 131 * <p>This is a convenience constructor and maintains the password internally via a character 132 * array, i.e. <tt>password.toCharArray();</tt>. Note that storing a password as a String 133 * in your code could have possible security implications as noted in the class JavaDoc.</p> 134 * 135 * @param username the username submitted for authentication 136 * @param password the password string submitted for authentication 137 * @param host the host name or IP string from where the attempt is occurring 138 * @since 1.0 139 */ 140 public UsernamePasswordToken(final String username, final String password, final String host) { 141 this(username, password != null ? password.toCharArray() : null, false, host); 142 } 143 144 /** 145 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted, as well as if the user 146 * wishes their identity to be remembered across sessions. 147 * 148 * @param username the username submitted for authentication 149 * @param password the password string submitted for authentication 150 * @param rememberMe if the user wishes their identity to be remembered across sessions 151 * @since 0.9 152 */ 153 public UsernamePasswordToken(final String username, final char[] password, final boolean rememberMe) { 154 this(username, password, rememberMe, null); 155 } 156 157 /** 158 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted, as well as if the user 159 * wishes their identity to be remembered across sessions. 160 * <p/> 161 * <p>This is a convenience constructor and maintains the password internally via a character 162 * array, i.e. <tt>password.toCharArray();</tt>. Note that storing a password as a String 163 * in your code could have possible security implications as noted in the class JavaDoc.</p> 164 * 165 * @param username the username submitted for authentication 166 * @param password the password string submitted for authentication 167 * @param rememberMe if the user wishes their identity to be remembered across sessions 168 * @since 0.9 169 */ 170 public UsernamePasswordToken(final String username, final String password, final boolean rememberMe) { 171 this(username, password != null ? password.toCharArray() : null, rememberMe, null); 172 } 173 174 /** 175 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted, if the user 176 * wishes their identity to be remembered across sessions, and the inetAddress from where the attempt is occurring. 177 * 178 * @param username the username submitted for authentication 179 * @param password the password character array submitted for authentication 180 * @param rememberMe if the user wishes their identity to be remembered across sessions 181 * @param host the host name or IP string from where the attempt is occurring 182 * @since 1.0 183 */ 184 public UsernamePasswordToken(final String username, final char[] password, 185 final boolean rememberMe, final String host) { 186 187 this.username = username; 188 this.password = password; 189 this.rememberMe = rememberMe; 190 this.host = host; 191 } 192 193 194 /** 195 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted, if the user 196 * wishes their identity to be remembered across sessions, and the inetAddress from where the attempt is occurring. 197 * <p/> 198 * <p>This is a convenience constructor and maintains the password internally via a character 199 * array, i.e. <tt>password.toCharArray();</tt>. Note that storing a password as a String 200 * in your code could have possible security implications as noted in the class JavaDoc.</p> 201 * 202 * @param username the username submitted for authentication 203 * @param password the password string submitted for authentication 204 * @param rememberMe if the user wishes their identity to be remembered across sessions 205 * @param host the host name or IP string from where the attempt is occurring 206 * @since 1.0 207 */ 208 public UsernamePasswordToken(final String username, final String password, 209 final boolean rememberMe, final String host) { 210 this(username, password != null ? password.toCharArray() : null, rememberMe, host); 211 } 212 213 /*-------------------------------------------- 214 | A C C E S S O R S / M O D I F I E R S | 215 ============================================*/ 216 217 /** 218 * Returns the username submitted during an authentication attempt. 219 * 220 * @return the username submitted during an authentication attempt. 221 */ 222 public String getUsername() { 223 return username; 224 } 225 226 /** 227 * Sets the username for submission during an authentication attempt. 228 * 229 * @param username the username to be used for submission during an authentication attempt. 230 */ 231 public void setUsername(String username) { 232 this.username = username; 233 } 234 235 236 /** 237 * Returns the password submitted during an authentication attempt as a character array. 238 * 239 * @return the password submitted during an authentication attempt as a character array. 240 */ 241 public char[] getPassword() { 242 return password; 243 } 244 245 /** 246 * Sets the password for submission during an authentication attempt. 247 * 248 * @param password the password to be used for submission during an authentication attempt. 249 */ 250 public void setPassword(char[] password) { 251 this.password = password; 252 } 253 254 /** 255 * Simply returns {@link #getUsername() getUsername()}. 256 * 257 * @return the {@link #getUsername() username}. 258 * @see org.apache.shiro.authc.AuthenticationToken#getPrincipal() 259 */ 260 public Object getPrincipal() { 261 return getUsername(); 262 } 263 264 /** 265 * Returns the {@link #getPassword() password} char array. 266 * 267 * @return the {@link #getPassword() password} char array. 268 * @see org.apache.shiro.authc.AuthenticationToken#getCredentials() 269 */ 270 public Object getCredentials() { 271 return getPassword(); 272 } 273 274 /** 275 * Returns the host name or IP string from where the authentication attempt occurs. May be <tt>null</tt> if the 276 * host name/IP is unknown or explicitly omitted. It is up to the Authenticator implementation processing this 277 * token if an authentication attempt without a host is valid or not. 278 * <p/> 279 * <p>(Shiro's default Authenticator allows <tt>null</tt> hosts to support localhost and proxy server environments).</p> 280 * 281 * @return the host from where the authentication attempt occurs, or <tt>null</tt> if it is unknown or 282 * explicitly omitted. 283 * @since 1.0 284 */ 285 public String getHost() { 286 return host; 287 } 288 289 /** 290 * Sets the host name or IP string from where the authentication attempt occurs. It is up to the Authenticator 291 * implementation processing this token if an authentication attempt without a host is valid or not. 292 * <p/> 293 * <p>(Shiro's default Authenticator 294 * allows <tt>null</tt> hosts to allow localhost and proxy server environments).</p> 295 * 296 * @param host the host name or IP string from where the attempt is occurring 297 * @since 1.0 298 */ 299 public void setHost(String host) { 300 this.host = host; 301 } 302 303 /** 304 * Returns <tt>true</tt> if the submitting user wishes their identity (principal(s)) to be remembered 305 * across sessions, <tt>false</tt> otherwise. Unless overridden, this value is <tt>false</tt> by default. 306 * 307 * @return <tt>true</tt> if the submitting user wishes their identity (principal(s)) to be remembered 308 * across sessions, <tt>false</tt> otherwise (<tt>false</tt> by default). 309 * @since 0.9 310 */ 311 public boolean isRememberMe() { 312 return rememberMe; 313 } 314 315 /** 316 * Sets if the submitting user wishes their identity (principal(s)) to be remembered across sessions. Unless 317 * overridden, the default value is <tt>false</tt>, indicating <em>not</em> to be remembered across sessions. 318 * 319 * @param rememberMe value indicating if the user wishes their identity (principal(s)) to be remembered across 320 * sessions. 321 * @since 0.9 322 */ 323 public void setRememberMe(boolean rememberMe) { 324 this.rememberMe = rememberMe; 325 } 326 327 /*-------------------------------------------- 328 | M E T H O D S | 329 ============================================*/ 330 331 /** 332 * Clears out (nulls) the username, password, rememberMe, and inetAddress. The password bytes are explicitly set to 333 * <tt>0x00</tt> before nulling to eliminate the possibility of memory access at a later time. 334 */ 335 public void clear() { 336 this.username = null; 337 this.host = null; 338 this.rememberMe = false; 339 340 if (this.password != null) { 341 for (int i = 0; i < password.length; i++) { 342 this.password[i] = 0x00; 343 } 344 this.password = null; 345 } 346 347 } 348 349 /** 350 * Returns the String representation. It does not include the password in the resulting 351 * string for security reasons to prevent accidentally printing out a password 352 * that might be widely viewable). 353 * 354 * @return the String representation of the <tt>UsernamePasswordToken</tt>, omitting 355 * the password. 356 */ 357 public String toString() { 358 StringBuilder sb = new StringBuilder(); 359 sb.append(getClass().getName()); 360 sb.append(" - "); 361 sb.append(username); 362 sb.append(", rememberMe=").append(rememberMe); 363 if (host != null) { 364 sb.append(" (").append(host).append(")"); 365 } 366 return sb.toString(); 367 } 368 369 }