001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.shiro.authc;
020
021 /**
022 * <p>A simple username/password authentication token to support the most widely-used authentication mechanism. This
023 * class also implements the {@link RememberMeAuthenticationToken RememberMeAuthenticationToken} interface to support
024 * "Remember Me" services across user sessions as well as the
025 * {@link org.apache.shiro.authc.HostAuthenticationToken HostAuthenticationToken} interface to retain the host name
026 * or IP address location from where the authentication attempt is occuring.</p>
027 * <p/>
028 * <p>"Remember Me" authentications are disabled by default, but if the application developer wishes to allow
029 * it for a login attempt, all that is necessary is to call {@link #setRememberMe setRememberMe(true)}. If the underlying
030 * <tt>SecurityManager</tt> implementation also supports <tt>RememberMe</tt> services, the user's identity will be
031 * remembered across sessions.
032 * <p/>
033 * <p>Note that this class stores a password as a char[] instead of a String
034 * (which may seem more logical). This is because Strings are immutable and their
035 * internal value cannot be overwritten - meaning even a nulled String instance might be accessible in memory at a later
036 * time (e.g. memory dump). This is not good for sensitive information such as passwords. For more information, see the
037 * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/security/jce/JCERefGuide.html#PBEEx">
038 * Java Cryptography Extension Reference Guide</a>.</p>
039 * <p/>
040 * <p>To avoid this possibility of later memory access, the application developer should always call
041 * {@link #clear() clear()} after using the token to perform a login attempt.</p>
042 *
043 * @author Jeremy Haile
044 * @author Les Hazlewood
045 * @since 0.1
046 */
047 public class UsernamePasswordToken implements HostAuthenticationToken, RememberMeAuthenticationToken {
048
049 /*--------------------------------------------
050 | C O N S T A N T S |
051 ============================================*/
052
053 /*--------------------------------------------
054 | I N S T A N C E V A R I A B L E S |
055 ============================================*/
056 /**
057 * The username
058 */
059 private String username;
060
061 /**
062 * The password, in char[] format
063 */
064 private char[] password;
065
066 /**
067 * Whether or not 'rememberMe' should be enabled for the corresponding login attempt;
068 * default is <code>false</code>
069 */
070 private boolean rememberMe = false;
071
072 /**
073 * The location from where the login attempt occurs, or <code>null</code> if not known or explicitly
074 * omitted.
075 */
076 private String host;
077
078 /*--------------------------------------------
079 | C O N S T R U C T O R S |
080 ============================================*/
081
082 /**
083 * JavaBeans compatible no-arg constructor.
084 */
085 public UsernamePasswordToken() {
086 }
087
088 /**
089 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted
090 * during an authentication attempt, with a <tt>null</tt> {@link #getHost() host} and a
091 * <tt>rememberMe</tt> default of <tt>false</tt>.
092 *
093 * @param username the username submitted for authentication
094 * @param password the password character array submitted for authentication
095 */
096 public UsernamePasswordToken(final String username, final char[] password) {
097 this(username, password, false, null);
098 }
099
100 /**
101 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted
102 * during an authentication attempt, with a <tt>null</tt> {@link #getHost() host} and
103 * a <tt>rememberMe</tt> default of <tt>false</tt>
104 * <p/>
105 * <p>This is a convience constructor and maintains the password internally via a character
106 * array, i.e. <tt>password.toCharArray();</tt>. Note that storing a password as a String
107 * in your code could have possible security implications as noted in the class JavaDoc.</p>
108 *
109 * @param username the username submitted for authentication
110 * @param password the password string submitted for authentication
111 */
112 public UsernamePasswordToken(final String username, final String password) {
113 this(username, password != null ? password.toCharArray() : null, false, null);
114 }
115
116 /**
117 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted, the
118 * inetAddress from where the attempt is occurring, and a default <tt>rememberMe</tt> value of <tt>false</tt>
119 *
120 * @param username the username submitted for authentication
121 * @param password the password string submitted for authentication
122 * @param host the host name or IP string from where the attempt is occuring
123 * @since 0.2
124 */
125 public UsernamePasswordToken(final String username, final char[] password, final String host) {
126 this(username, password, false, host);
127 }
128
129 /**
130 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted, the
131 * inetAddress from where the attempt is occurring, and a default <tt>rememberMe</tt> value of <tt>false</tt>
132 * <p/>
133 * <p>This is a convience constructor and maintains the password internally via a character
134 * array, i.e. <tt>password.toCharArray();</tt>. Note that storing a password as a String
135 * in your code could have possible security implications as noted in the class JavaDoc.</p>
136 *
137 * @param username the username submitted for authentication
138 * @param password the password string submitted for authentication
139 * @param host the host name or IP string from where the attempt is occuring
140 * @since 1.0
141 */
142 public UsernamePasswordToken(final String username, final String password, final String host) {
143 this(username, password != null ? password.toCharArray() : null, false, host);
144 }
145
146 /**
147 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted, as well as if the user
148 * wishes their identity to be remembered across sessions.
149 *
150 * @param username the username submitted for authentication
151 * @param password the password string submitted for authentication
152 * @param rememberMe if the user wishes their identity to be remembered across sessions
153 * @since 0.9
154 */
155 public UsernamePasswordToken(final String username, final char[] password, final boolean rememberMe) {
156 this(username, password, rememberMe, null);
157 }
158
159 /**
160 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted, as well as if the user
161 * wishes their identity to be remembered across sessions.
162 * <p/>
163 * <p>This is a convience constructor and maintains the password internally via a character
164 * array, i.e. <tt>password.toCharArray();</tt>. Note that storing a password as a String
165 * in your code could have possible security implications as noted in the class JavaDoc.</p>
166 *
167 * @param username the username submitted for authentication
168 * @param password the password string submitted for authentication
169 * @param rememberMe if the user wishes their identity to be remembered across sessions
170 * @since 0.9
171 */
172 public UsernamePasswordToken(final String username, final String password, final boolean rememberMe) {
173 this(username, password != null ? password.toCharArray() : null, rememberMe, null);
174 }
175
176 /**
177 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted, if the user
178 * wishes their identity to be remembered across sessions, and the inetAddress from where the attempt is ocurring.
179 *
180 * @param username the username submitted for authentication
181 * @param password the password character array submitted for authentication
182 * @param rememberMe if the user wishes their identity to be remembered across sessions
183 * @param host the host name or IP string from where the attempt is occuring
184 * @since 1.0
185 */
186 public UsernamePasswordToken(final String username, final char[] password,
187 final boolean rememberMe, final String host) {
188
189 this.username = username;
190 this.password = password;
191 this.rememberMe = rememberMe;
192 this.host = host;
193 }
194
195
196 /**
197 * Constructs a new UsernamePasswordToken encapsulating the username and password submitted, if the user
198 * wishes their identity to be remembered across sessions, and the inetAddress from where the attempt is ocurring.
199 * <p/>
200 * <p>This is a convience constructor and maintains the password internally via a character
201 * array, i.e. <tt>password.toCharArray();</tt>. Note that storing a password as a String
202 * in your code could have possible security implications as noted in the class JavaDoc.</p>
203 *
204 * @param username the username submitted for authentication
205 * @param password the password string submitted for authentication
206 * @param rememberMe if the user wishes their identity to be remembered across sessions
207 * @param host the host name or IP string from where the attempt is occuring
208 * @since 1.0
209 */
210 public UsernamePasswordToken(final String username, final String password,
211 final boolean rememberMe, final String host) {
212 this(username, password != null ? password.toCharArray() : null, rememberMe, host);
213 }
214
215 /*--------------------------------------------
216 | A C C E S S O R S / M O D I F I E R S |
217 ============================================*/
218
219 /**
220 * Returns the username submitted during an authentication attempt.
221 *
222 * @return the username submitted during an authentication attempt.
223 */
224 public String getUsername() {
225 return username;
226 }
227
228 /**
229 * Sets the username for submission during an authentication attempt.
230 *
231 * @param username the username to be used for submission during an authentication attempt.
232 */
233 public void setUsername(String username) {
234 this.username = username;
235 }
236
237
238 /**
239 * Returns the password submitted during an authentication attempt as a character array.
240 *
241 * @return the password submitted during an authentication attempt as a character array.
242 */
243 public char[] getPassword() {
244 return password;
245 }
246
247 /**
248 * Sets the password for submission during an authentication attempt.
249 *
250 * @param password the password to be used for submission during an authentication attemp.
251 */
252 public void setPassword(char[] password) {
253 this.password = password;
254 }
255
256 /**
257 * Simply returns {@link #getUsername() getUsername()}.
258 *
259 * @return the {@link #getUsername() username}.
260 * @see org.apache.shiro.authc.AuthenticationToken#getPrincipal()
261 */
262 public Object getPrincipal() {
263 return getUsername();
264 }
265
266 /**
267 * Returns the {@link #getPassword() password} char array.
268 *
269 * @return the {@link #getPassword() password} char array.
270 * @see org.apache.shiro.authc.AuthenticationToken#getCredentials()
271 */
272 public Object getCredentials() {
273 return getPassword();
274 }
275
276 /**
277 * Returns the host name or IP string from where the authentication attempt occurs. May be <tt>null</tt> if the
278 * host name/IP is unknown or explicitly omitted. It is up to the Authenticator implementation processing this
279 * token if an authentication attempt without a host is valid or not.
280 * <p/>
281 * <p>(Shiro's default Authenticator allows <tt>null</tt> hosts to support localhost and proxy server environments).</p>
282 *
283 * @return the host from where the authentication attempt occurs, or <tt>null</tt> if it is unknown or
284 * explicitly omitted.
285 * @since 1.0
286 */
287 public String getHost() {
288 return host;
289 }
290
291 /**
292 * Sets the host name or IP string from where the authentication attempt occurs. It is up to the Authenticator
293 * implementation processing this token if an authentication attempt without a host is valid or not.
294 * <p/>
295 * <p>(Shiro's default Authenticator
296 * allows <tt>null</tt> hosts to allow localhost and proxy server environments).</p>
297 *
298 * @param host the host name or IP string from where the attempt is occuring
299 * @since 1.0
300 */
301 public void setHost(String host) {
302 this.host = host;
303 }
304
305 /**
306 * Returns <tt>true</tt> if the submitting user wishes their identity (principal(s)) to be remembered
307 * across sessions, <tt>false</tt> otherwise. Unless overridden, this value is <tt>false</tt> by default.
308 *
309 * @return <tt>true</tt> if the submitting user wishes their identity (principal(s)) to be remembered
310 * across sessions, <tt>false</tt> otherwise (<tt>false</tt> by default).
311 * @since 0.9
312 */
313 public boolean isRememberMe() {
314 return rememberMe;
315 }
316
317 /**
318 * Sets if the submitting user wishes their identity (pricipal(s)) to be remembered across sessions. Unless
319 * overridden, the default value is <tt>false</tt>, indicating <em>not</em> to be remembered across sessions.
320 *
321 * @param rememberMe value inidicating if the user wishes their identity (principal(s)) to be remembered across
322 * sessions.
323 * @since 0.9
324 */
325 public void setRememberMe(boolean rememberMe) {
326 this.rememberMe = rememberMe;
327 }
328
329 /*--------------------------------------------
330 | M E T H O D S |
331 ============================================*/
332
333 /**
334 * Clears out (nulls) the username, password, rememberMe, and inetAddress. The password bytes are explicitly set to
335 * <tt>0x00</tt> before nulling to eliminate the possibility of memory access at a later time.
336 */
337 public void clear() {
338 this.username = null;
339 this.host = null;
340 this.rememberMe = false;
341
342 if (this.password != null) {
343 for (int i = 0; i < password.length; i++) {
344 this.password[i] = 0x00;
345 }
346 this.password = null;
347 }
348
349 }
350
351 /**
352 * Returns the String representation. It does not include the password in the resulting
353 * string for security reasons to prevent accidentially printing out a password
354 * that might be widely viewable).
355 *
356 * @return the String representation of the <tt>UsernamePasswordToken</tt>, omitting
357 * the password.
358 */
359 public String toString() {
360 StringBuffer sb = new StringBuffer();
361 sb.append(getClass().getName());
362 sb.append(" - ");
363 sb.append(username);
364 sb.append(", rememberMe=").append(rememberMe);
365 if (host != null) {
366 sb.append(" (").append(host).append(")");
367 }
368 return sb.toString();
369 }
370
371 }