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.credential;
020
021 import org.apache.shiro.util.ByteSource;
022
023 /**
024 * A {@code PasswordService} supports common use cases when using passwords as a credentials mechanism.
025 * <p/>
026 * Most importantly, implementations of this interface are expected to employ best-practices to ensure that
027 * passwords remain as safe as possible in application environments.
028 * <h2>Usage</h2>
029 * A {@code PasswordService} is used at two different times during an application's lifecycle:
030 * <ul>
031 * <li>When creating a user account or resetting their password</li>
032 * <li>When a user logs in, when passwords must be compared</li>
033 * </ul>
034 * <h3>Account Creation or Password Reset</h3>
035 * Whenever you create a new user account or reset that account's password, we must translate the end-user submitted
036 * raw/plaintext password value to a string format that is much safer to store. You do that by calling the
037 * {@link #encryptPassword(Object)} method to create the safer value. For
038 * example:
039 * <pre>
040 * String submittedPlaintextPassword = ...
041 * String encryptedValue = passwordService.encryptPassword(submittedPlaintextPassword);
042 * ...
043 * userAccount.setPassword(encryptedValue);
044 * userAccount.save(); //create or update to your data store
045 * </pre>
046 * Be sure to save this encrypted password in your data store and never the original/raw submitted password.
047 * <h3>Login Password Comparison</h3>
048 * Shiro performs the comparison during login automatically. Along with your {@code PasswordService}, you just
049 * have to configure a {@link PasswordMatcher} on a realm that has password-based accounts. During a login attempt,
050 * shiro will use the {@code PasswordMatcher} and the {@code PasswordService} to automatically compare submitted
051 * passwords.
052 * <p/>
053 * For example, if using Shiro's INI, here is how you might configure the PasswordMatcher and PasswordService:
054 * <pre>
055 * [main]
056 * ...
057 * passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
058 * # configure the passwordService to use the settings you desire
059 * ...
060 * passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher
061 * passwordMatcher.passwordService = $passwordService
062 * ...
063 * # Finally, set the matcher on a realm that requires password matching for account authentication:
064 * myRealm = ...
065 * myRealm.credentialsMatcher = $passwordMatcher
066 * </pre>
067 *
068 * @see DefaultPasswordService
069 * @see PasswordMatcher
070 * @since 1.2
071 */
072 public interface PasswordService {
073
074 /**
075 * Converts the specified plaintext password (usually acquired from your application's 'new user' or 'password reset'
076 * workflow) into a formatted string safe for storage. The returned string can be safely saved with the
077 * corresponding user account record (e.g. as a 'password' attribute).
078 * <p/>
079 * It is expected that the String returned from this method will be presented to the
080 * {@link #passwordsMatch(Object, String) passwordsMatch(plaintext,encrypted)} method when performing a
081 * password comparison check.
082 * <h3>Usage</h3>
083 * The input argument type can be any 'byte backed' {@code Object} - almost always either a
084 * String or character array representing passwords (character arrays are often a safer way to represent passwords
085 * as they can be cleared/nulled-out after use. Any argument type supported by
086 * {@link ByteSource.Util#isCompatible(Object)} is valid.
087 * <p/>
088 * For example:
089 * <pre>
090 * String rawPassword = ...
091 * String encryptedValue = passwordService.encryptPassword(rawPassword);
092 * </pre>
093 * or, identically:
094 * <pre>
095 * char[] rawPasswordChars = ...
096 * String encryptedValue = passwordService.encryptPassword(rawPasswordChars);
097 * </pre>
098 * <p/>
099 * 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 }