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 */ 019package org.apache.shiro.authc.credential; 020 021import 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 */ 072public 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}