View Javadoc

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   * &quot;Remember Me&quot; 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 occuring.</p>
27   * <p/>
28   * <p>&quot;Remember Me&quot; 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 = false;
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 convience 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 occuring
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 convience 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 occuring
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 convience 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 ocurring.
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 occuring
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 ocurring.
197      * <p/>
198      * <p>This is a convience 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 occuring
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 attemp.
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 occuring
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 (pricipal(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 inidicating 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 accidentially 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 }