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 }