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.credential;
20  
21  import org.apache.shiro.util.ByteSource;
22  
23  /**
24   * A {@code PasswordService} supports common use cases when using passwords as a credentials mechanism.
25   * <p/>
26   * Most importantly, implementations of this interface are expected to employ best-practices to ensure that
27   * passwords remain as safe as possible in application environments.
28   * <h2>Usage</h2>
29   * A {@code PasswordService} is used at two different times during an application's lifecycle:
30   * <ul>
31   * <li>When creating a user account or resetting their password</li>
32   * <li>When a user logs in, when passwords must be compared</li>
33   * </ul>
34   * <h3>Account Creation or Password Reset</h3>
35   * Whenever you create a new user account or reset that account's password, we must translate the end-user submitted
36   * raw/plaintext password value to a string format that is much safer to store.  You do that by calling the
37   * {@link #encryptPassword(Object)} method to create the safer value.  For
38   * example:
39   * <pre>
40   * String submittedPlaintextPassword = ...
41   * String encryptedValue = passwordService.encryptPassword(submittedPlaintextPassword);
42   * ...
43   * userAccount.setPassword(encryptedValue);
44   * userAccount.save(); //create or update to your data store
45   * </pre>
46   * Be sure to save this encrypted password in your data store and never the original/raw submitted password.
47   * <h3>Login Password Comparison</h3>
48   * Shiro performs the comparison during login automatically.  Along with your {@code PasswordService}, you just
49   * have to configure a {@link PasswordMatcher} on a realm that has password-based accounts.   During a login attempt,
50   * shiro will use the {@code PasswordMatcher} and the {@code PasswordService} to automatically compare submitted
51   * passwords.
52   * <p/>
53   * For example, if using Shiro's INI, here is how you might configure the PasswordMatcher and PasswordService:
54   * <pre>
55   * [main]
56   * ...
57   * passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
58   * # configure the passwordService to use the settings you desire
59   * ...
60   * passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher
61   * passwordMatcher.passwordService = $passwordService
62   * ...
63   * # Finally, set the matcher on a realm that requires password matching for account authentication:
64   * myRealm = ...
65   * myRealm.credentialsMatcher = $passwordMatcher
66   * </pre>
67   *
68   * @see DefaultPasswordService
69   * @see PasswordMatcher
70   * @since 1.2
71   */
72  public interface PasswordService {
73  
74      /**
75       * Converts the specified plaintext password (usually acquired from your application's 'new user' or 'password reset'
76       * workflow) into a formatted string safe for storage.  The returned string can be safely saved with the
77       * corresponding user account record (e.g. as a 'password' attribute).
78       * <p/>
79       * It is expected that the String returned from this method will be presented to the
80       * {@link #passwordsMatch(Object, String) passwordsMatch(plaintext,encrypted)} method when performing a
81       * password comparison check.
82       * <h3>Usage</h3>
83       * The input argument type can be any 'byte backed' {@code Object} - almost always either a
84       * String or character array representing passwords (character arrays are often a safer way to represent passwords
85       * as they can be cleared/nulled-out after use.  Any argument type supported by
86       * {@link ByteSource.Util#isCompatible(Object)} is valid.
87       * <p/>
88       * For example:
89       * <pre>
90       * String rawPassword = ...
91       * String encryptedValue = passwordService.encryptPassword(rawPassword);
92       * </pre>
93       * or, identically:
94       * <pre>
95       * char[] rawPasswordChars = ...
96       * String encryptedValue = passwordService.encryptPassword(rawPasswordChars);
97       * </pre>
98       * <p/>
99       * The resulting {@code encryptedValue} should be stored with the account to be retrieved later during a
100      * login attempt.  For example:
101      * <pre>
102      * String encryptedValue = passwordService.encryptPassword(rawPassword);
103      * ...
104      * userAccount.setPassword(encryptedValue);
105      * userAccount.save(); //create or update to your data store
106      * </pre>
107      *
108      * @param plaintextPassword the raw password as 'byte-backed' object (String, character array, {@link ByteSource},
109      *                          etc) usually acquired from your application's 'new user' or 'password reset' workflow.
110      * @return the encrypted password, formatted for storage.
111      * @throws IllegalArgumentException if the argument cannot be easily converted to bytes as defined by
112      *                                  {@link ByteSource.Util#isCompatible(Object)}.
113      * @see ByteSource.Util#isCompatible(Object)
114      */
115     String encryptPassword(Object plaintextPassword) throws IllegalArgumentException;
116 
117     /**
118      * Returns {@code true} if the {@code submittedPlaintext} password matches the existing {@code saved} password,
119      * {@code false} otherwise.
120      * <h3>Usage</h3>
121      * The {@code submittedPlaintext} argument type can be any 'byte backed' {@code Object} - almost always either a
122      * String or character array representing passwords (character arrays are often a safer way to represent passwords
123      * as they can be cleared/nulled-out after use.  Any argument type supported by
124      * {@link ByteSource.Util#isCompatible(Object)} is valid.
125      * <p/>
126      * For example:
127      * <pre>
128      * String submittedPassword = ...
129      * passwordService.passwordsMatch(submittedPassword, encryptedPassword);
130      * </pre>
131      * or similarly:
132      * <pre>
133      * char[] submittedPasswordCharacters = ...
134      * passwordService.passwordsMatch(submittedPasswordCharacters, encryptedPassword);
135      * </pre>
136      *
137      * @param submittedPlaintext a raw/plaintext password submitted by an end user/Subject.
138      * @param encrypted          the previously encrypted password known to be associated with an account.
139      *                           This value is expected to have been previously generated from the
140      *                           {@link #encryptPassword(Object) encryptPassword} method (typically
141      *                           when the account is created or the account's password is reset).
142      * @return {@code true} if the {@code submittedPlaintext} password matches the existing {@code saved} password,
143      *         {@code false} otherwise.
144      * @see ByteSource.Util#isCompatible(Object)
145      */
146     boolean passwordsMatch(Object submittedPlaintext, String encrypted);
147 }