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 }