Class HashedCredentialsMatcher
java.lang.Object
org.apache.shiro.lang.codec.CodecSupport
org.apache.shiro.authc.credential.SimpleCredentialsMatcher
org.apache.shiro.authc.credential.HashedCredentialsMatcher
- All Implemented Interfaces:
CredentialsMatcher
- Direct Known Subclasses:
Sha256CredentialsMatcher,Sha384CredentialsMatcher,Sha512CredentialsMatcher
A
HashedCredentialMatcher provides support for hashing of supplied AuthenticationToken credentials
before being compared to those in the AuthenticationInfo from the data store.
Credential hashing is one of the most common security techniques when safeguarding a user's private credentials
(passwords, keys, etc.). Most developers never want to store their users' credentials in plain form, viewable by
anyone, so they often hash the users' credentials before they are saved in the data store.
This class (and its subclasses) function as follows:
- Hash the
AuthenticationTokencredentials supplied by the user during their login. - Compare this hashed value directly with the
AuthenticationInfocredentials stored in the system (the stored account credentials are expected to already be in hashed form). - If these two values are
equal, the submitted credentials match, otherwise they do not.
Salting and Multiple Hash Iterations
Because simple hashing is usually not good enough for secure applications, this class also supports 'salting' and multiple hash iterations. Please read this excellent invalid input: '<'a href="http://www.owasp.org/index.php/Hashing_Java" _target="blank">Hashing Java article to learn about salting and multiple iterations and why you might want to use them. (Note of sections 5 "Why add salt?" and 6 "Hardening against the attacker's attack").Real World Case Study
In April 2010, some public Atlassian Jira and Confluence installations (Apache Software Foundation, Codehaus, etc.) were the target of account attacks and user accounts were compromised. The reason? Jira and Confluence at the time did not salt user passwords and attackers were able to use dictionary attacks to compromise user accounts (Atlassian has since fixed the problem of course). The lesson? ALWAYS, ALWAYS, ALWAYS SALT USER PASSWORDS!Salting
Prior to Shiro 1.1, salts could be obtained based on the end-user submittedAuthenticationToken via the now-deprecated
getSalt(AuthenticationToken) method. This however
could constitute a security hole since ideally salts should never be obtained based on what a user can submit.
User-submitted salt mechanisms are much more susceptible to dictionary attacks and SHOULD NOT be
used in secure systems. Instead, salts should ideally be a secure randomly-generated number that is generated when
the user account is created. The secure number should never be disseminated to the user and always kept private
by the application.
Shiro 1.1
As of Shiro 1.1, it is expected that any salt used to hash the submitted credentials will be obtained from the stored account information (represented as anAuthenticationInfo instance). This is much
more secure because the salt value remains private to the application (Shiro will never store this value).
To enable this, Realms should return SaltedAuthenticationInfo instances
during authentication. HashedCredentialsMatcher implementations will then use the provided
credentialsSalt for hashing. To avoid
security risks,
it is highly recommended that any existing Realm implementations that support hashed credentials are
updated to return SaltedAuthenticationInfo instances as soon as possible.
Shiro 1.0 Backwards Compatibility
Because of the identified security risk,Realm implementations that support credentials hashing should
be updated to return SaltedAuthenticationInfo instances as
soon as possible.
If this is not possible for some reason, this class will retain 1.0 backwards-compatible behavior of obtaining
the salt via the now-deprecated getSalt(AuthenticationToken) method. This
method will only be invoked if a Realm does not return
SaltedAuthenticationInfo instances and hashSalted is
true.
But please note that the hashSalted property and the
getSalt(AuthenticationToken) methods will be removed before the Shiro 2.0
release.
Multiple Hash Iterations
If you hash your users' credentials multiple times before persisting to the data store, you will also need to set this class'shashIterations property. See the
invalid input: '<'a href="http://www.owasp.org/index.php/Hashing_Java" _target="blank">Hashing Java article's
"Hardening against the attacker's attack" section to learn more about why you might want to use
multiple hash iterations.
MD5 & SHA-1 Notice
MD5 and SHA-1 algorithms are now known to be vulnerable to compromise and/or collisions (read the linked pages for more). While most applications are ok with either of these two, if your application mandates high security, use the SHA-256 (or higher) hashing algorithms and their supportingCredentialsMatcher implementations.- Since:
- 0.9
- See Also:
-
Field Summary
Fields inherited from class org.apache.shiro.lang.codec.CodecSupport
PREFERRED_ENCODING -
Constructor Summary
ConstructorsConstructorDescriptionJavaBeans-compatible no-arg constructor intended for use in IoC/Dependency Injection environments.HashedCredentialsMatcher(String hashAlgorithmName) Creates an instance using the specifiedhashAlgorithmNameto hash submitted credentials. -
Method Summary
Modifier and TypeMethodDescriptionbooleandoCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) This implementation first hashes thetoken's credentials, potentially using asaltif theinfoargument is aSaltedAuthenticationInfo.protected ObjectReturns aHashinstance representing the already-hashed AuthenticationInfo credentials stored in the system.Returns theHashalgorithmNameto use when performing hashes for credentials matching.intReturns the number of times a submittedAuthenticationToken's credentials will be hashed before comparing to the credentials stored in the system.protected ObjectgetSalt(AuthenticationToken token) Deprecated.since Shiro 1.1.protected org.apache.shiro.crypto.hash.HashhashProvidedCredentials(Object credentials, Object salt, int hashIterations) Hashes the provided credentials a total ofhashIterationstimes, using the given salt.protected ObjecthashProvidedCredentials(AuthenticationToken token, AuthenticationInfo info) Hash the providedtoken's credentials using the salt stored with the account if theinfoinstance is aninstanceofSaltedAuthenticationInfo(see the class-level JavaDoc for why this is the preferred approach).booleanDeprecated.since Shiro 1.1.booleanReturnstrueif the system's stored credential hash is Hex encoded,falseif it is Base64 encoded.protected org.apache.shiro.crypto.hash.SimpleHashReturns a new, uninitialized instance, without its byte array set.voidsetHashAlgorithmName(String hashAlgorithmName) Sets theHashalgorithmNameto use when performing hashes for credentials matching.voidsetHashIterations(int hashIterations) Sets the number of times a submittedAuthenticationToken's credentials will be hashed before comparing to the credentials stored in the system.voidsetHashSalted(boolean hashSalted) Deprecated.since Shiro 1.1.voidsetStoredCredentialsHexEncoded(boolean storedCredentialsHexEncoded) Sets the indicator if this system's stored credential hash is Hex encoded or not.Methods inherited from class org.apache.shiro.authc.credential.SimpleCredentialsMatcher
equals, getCredentialsMethods inherited from class org.apache.shiro.lang.codec.CodecSupport
isByteSource, objectToBytes, objectToString, toBytes, toBytes, toBytes, toBytes, toBytes, toBytes, toBytes, toChars, toChars, toString, toString, toString
-
Constructor Details
-
HashedCredentialsMatcher
public HashedCredentialsMatcher()JavaBeans-compatible no-arg constructor intended for use in IoC/Dependency Injection environments. If you use this constructor, you MUST also additionally set thehashAlgorithmNameproperty. -
HashedCredentialsMatcher
Creates an instance using the specifiedhashAlgorithmNameto hash submitted credentials.- Parameters:
hashAlgorithmName- theHashalgorithmNameto use when performing hashes for credentials matching.- Since:
- 1.1
-
-
Method Details
-
getHashAlgorithmName
Returns theHashalgorithmNameto use when performing hashes for credentials matching.- Returns:
- the
HashalgorithmNameto use when performing hashes for credentials matching. - Since:
- 1.1
-
setHashAlgorithmName
Sets theHashalgorithmNameto use when performing hashes for credentials matching.- Parameters:
hashAlgorithmName- theHashalgorithmNameto use when performing hashes for credentials matching.- Since:
- 1.1
-
isStoredCredentialsHexEncoded
Returnstrueif the system's stored credential hash is Hex encoded,falseif it is Base64 encoded. Default value istruefor convenience - all of Shiro'sHash#toString()implementations return Hex encoded values by default, making this class's use with those implementations easier.- Returns:
trueif the system's stored credential hash is Hex encoded,falseif it is Base64 encoded. Default istrue
-
setStoredCredentialsHexEncoded
Sets the indicator if this system's stored credential hash is Hex encoded or not. A value oftruewill cause this class to decode the system credential from Hex, a value offalsewill cause this class to decode the system credential from Base64. Unless overridden via this method, the default value istruefor convenience - all of Shiro'sHash#toString()implementations return Hex encoded values by default, making this class's use with those implementations easier.- Parameters:
storedCredentialsHexEncoded- the indicator if this system's stored credential hash is Hex encoded or not ('not' automatically implying it is Base64 encoded).
-
isHashSalted
Deprecated.since Shiro 1.1. Hash salting is now expected to be based on if theAuthenticationInforeturned from theRealmis aSaltedAuthenticationInfoinstance and itsgetCredentialsSalt()method returns a non-null value. This method and the 1.0 behavior still exists for backwards compatibility if theRealmdoes not returnSaltedAuthenticationInfoinstances, but it is highly recommended thatRealmimplementations that support hashed credentials start returningSaltedAuthenticationInfoinstances as soon as possible. This is because salts should always be obtained from the stored account information and never be interpreted based on user/Subject-entered data. User-entered data is easier to compromise for attackers, whereas account-unique (and secure randomly-generated) salts never disseminated to the end-user are almost impossible to break. This method will be removed in Shiro 2.0.Returnstrueif a submittedAuthenticationToken's credentials should be salted when hashing,falseif it should not be salted. If enabled, the salt used will be obtained via thegetSaltmethod. The default value isfalse.- Returns:
trueif a submittedAuthenticationToken's credentials should be salted when hashing,falseif it should not be salted.
-
setHashSalted
Deprecated.since Shiro 1.1. Hash salting is now expected to be based on if theAuthenticationInforeturned from theRealmis aSaltedAuthenticationInfoinstance and itsgetCredentialsSalt()method returns a non-null value. This method and the 1.0 behavior still exists for backwards compatibility if theRealmdoes not returnSaltedAuthenticationInfoinstances, but it is highly recommended thatRealmimplementations that support hashed credentials start returningSaltedAuthenticationInfoinstances as soon as possible. This is because salts should always be obtained from the stored account information and never be interpreted based on user/Subject-entered data. User-entered data is easier to compromise for attackers, whereas account-unique (and secure randomly-generated) salts never disseminated to the end-user are almost impossible to break. This method will be removed in Shiro 2.0.Sets whether to salt a submittedAuthenticationToken's credentials when hashing. If enabled, the salt used will be obtained via thegetCredentialsSaltmethod. The default value isfalse.- Parameters:
hashSalted- whether to salt a submittedAuthenticationToken's credentials when hashing.
-
getHashIterations
Returns the number of times a submittedAuthenticationToken's credentials will be hashed before comparing to the credentials stored in the system. Unless overridden, the default value is1, meaning a normal hash execution will occur.- Returns:
- the number of times a submitted
AuthenticationToken's credentials will be hashed before comparing to the credentials stored in the system.
-
setHashIterations
Sets the number of times a submittedAuthenticationToken's credentials will be hashed before comparing to the credentials stored in the system. Unless overridden, the default value is1, meaning a normal single hash execution will occur. If this argument is less than 1 (i.e. 0 or negative), the default value of 1 is applied. There must always be at least 1 hash iteration (otherwise there would be no hash).- Parameters:
hashIterations- the number of times to hash a submittedAuthenticationToken's credentials.
-
getSalt
Deprecated.since Shiro 1.1. Hash salting is now expected to be based on if theAuthenticationInforeturned from theRealmis aSaltedAuthenticationInfoinstance and itsgetCredentialsSalt()method returns a non-null value. This method and the 1.0 behavior still exists for backwards compatibility if theRealmdoes not returnSaltedAuthenticationInfoinstances, but it is highly recommended thatRealmimplementations that support hashed credentials start returningSaltedAuthenticationInfoinstances as soon as possible. This is because salts should always be obtained from the stored account information and never be interpreted based on user/Subject-entered data. User-entered data is easier to compromise for attackers, whereas account-unique (and secure randomly-generated) salts never disseminated to the end-user are almost impossible to break. This method will be removed in Shiro 2.0.Returns a salt value used to hash the token's credentials. This default implementation merely returnstoken.getPrincipal(), effectively using the user's identity (username, user id, etc.) as the salt, a most common technique. If you wish to provide the authentication token's salt another way, you may override this method.- Parameters:
token- the AuthenticationToken submitted during the authentication attempt.- Returns:
- a salt value to use to hash the authentication token's credentials.
-
getCredentials
Returns aHashinstance representing the already-hashed AuthenticationInfo credentials stored in the system. This method reconstructs aHashinstance based on ainfo.getCredentialscall, but it does not hash that value - it is expected that method call will return an already-hashed value. This implementation's reconstruction effort functions as follows:- Convert
account.getCredentials()to a byte array via thetoBytesmethod. - If
account.getCredentials()was originally a String or char[] beforetoByteswas called, check for encoding: - If
storedCredentialsHexEncoded, Hex decode that byte array, otherwise Base64 decode the byte array - Set the byte[] array directly on the
Hashimplementation and return it.
- Overrides:
getCredentialsin classSimpleCredentialsMatcher- Parameters:
info- the AuthenticationInfo from which to retrieve the credentials which assumed to be in already-hashed form.- Returns:
- a
Hashinstance representing the given AuthenticationInfo's stored credentials.
- Convert
-
doCredentialsMatch
This implementation first hashes thetoken's credentials, potentially using asaltif theinfoargument is aSaltedAuthenticationInfo. It then compares the hash against theAuthenticationInfo'salready-hashed credentials. This method returnstrueif those two values areequal,falseotherwise.- Specified by:
doCredentialsMatchin interfaceCredentialsMatcher- Overrides:
doCredentialsMatchin classSimpleCredentialsMatcher- Parameters:
token- theAuthenticationTokensubmitted during the authentication attempt.info- theAuthenticationInfostored in the system matching the token principal- Returns:
trueif the provided token credentials hash match to the stored account credentials hash,falseotherwise- Since:
- 1.1
-
hashProvidedCredentials
Hash the providedtoken's credentials using the salt stored with the account if theinfoinstance is aninstanceofSaltedAuthenticationInfo(see the class-level JavaDoc for why this is the preferred approach). If theinfoinstance is not aninstanceofSaltedAuthenticationInfo, the logic will fall back to Shiro 1.0 backwards-compatible logic: it will first check to seeisHashSaltedand if so, will try to acquire the salt fromgetSalt(AuthenticationToken). See the class-level JavaDoc for why this is not recommended. This 'fallback' logic exists only for backwards-compatibility.Realms should be updated as soon as possible to returnSaltedAuthenticationInfoinstances if account credentials salting is enabled (highly recommended for password-based systems).- Parameters:
token- the submitted authentication token from which its credentials will be hashedinfo- the stored account data, potentially used to acquire a salt- Returns:
- the token credentials hash
- Since:
- 1.1
-
hashProvidedCredentials
protected org.apache.shiro.crypto.hash.Hash hashProvidedCredentials(Object credentials, Object salt, int hashIterations) Hashes the provided credentials a total ofhashIterationstimes, using the given salt. The hash implementation/algorithm used is based on thehashAlgorithmNameproperty.- Parameters:
credentials- the submitted authentication token's credentials to hashsalt- the value to salt the hash. Cannot benull, but an empty ByteSource.hashIterations- the number of times to hash the credentials. At least one hash will always occur though, even if this argument is 0 or negative.- Returns:
- the hashed value of the provided credentials, according to the specified salt and hash iterations.
- Throws:
NullPointerException- if salt isnull.
-
newHashInstance
Returns a new, uninitialized instance, without its byte array set. Used as a utility method in thegetCredentials(AuthenticationInfo)implementation.- Returns:
- a new, uninitialized instance, without its byte array set.
-