Fifth chapter code/Encryption--"Follow me to learn Shiro"

Source: Internet
Author: User


When it comes to password storage issues, you should encrypt/generate a password digest store instead of storing plaintext passwords. For example, the previous 600w csdn account leakage can cause a lot of loss to the user, so it should be encrypted/generated irreversible digest mode storage.

5.1 Encoding/decoding

Shiro provides API support for Base64 and 16 binary string encoding/decoding, which facilitates some encoding and decoding operations. The storage/representation of some data inside the Shiro uses both Base64 and 16 binary strings.

Java code
    1. String str = "Hello";
    2. String base64encoded = base64.encodetostring (Str.getbytes ());
    3. String str2 = base64.decodetostring (base64encoded);
    4. Assert.assertequals (str, str2);

The base64 encoding/decoding operation can be performed as above, and for more APIs please refer to its javadoc.

Java code
    1. String str = "Hello";
    2. String base64encoded = hex.encodetostring (Str.getbytes ());
    3. String str2 = new String (Hex.decode (Base64encoded.getbytes ()));
    4. Assert.assertequals (str, str2);

The 16-bit string encoding/decoding operation can be done as above, and more APIs refer to its Javadoc.

There is also a class codecsupport that may be used frequently, providing tobytes (str, "Utf-8")/toString (bytes, "Utf-8") to convert between byte array/string.

5.2 Hashing algorithm

Hash algorithm is generally used to generate data summary information, is an irreversible algorithm, generally suitable for storing data such as passwords, common hashing algorithms such as MD5, Sha and so on. Generally, it is best to provide a salt (salt), such as the encryption password "admin", the resulting hash value is "21232F297A57A5A743894A0E4A801FC3", you can go to some MD5 decrypt the site easily through the hash of the password "admin", That is, if it is easier to hash the password directly, then we can add some disturbing data that only the system knows, such as user name and ID (that is, salt), so that the Hashed object is "password + username +id", so that the generated hash value is relatively more difficult to crack.

Java code
    1. String str = "Hello";
    2. String Salt = "123";
    3. String MD5 = new Md5hash (str, salt). toString ();//can also be converted to toBase64 ()/tohex ()

As above code through Salt "123" MD5 hash "Hello". In addition hashing can also specify the number of hashes, such as 2 times: MD5 (MD5 (STR)): "New Md5hash (str, salt, 2). ToString ()".

Java code
    1. String str = "Hello";
    2. String Salt = "123";
    3. String SHA1 = new Sha256hash (str, salt). toString ();

Use the SHA256 algorithm to generate the corresponding hash data, as well as the SHA1, SHA512 algorithm.

Shiro also provides generic hashing support:

Java code
    1. String str = "Hello";
    2. String Salt = "123";
    3. Internal Use MessageDigest
    4. String Simplehash = new Simplehash ("SHA-1", str, salt). toString ();

The hash algorithm is specified by calling Simplehash, which uses the Java MessageDigest implementation internally.

For ease of use, Shiro provides the Hashservice, which provides the Defaulthashservice implementation by default.

Java code
  1. Defaulthashservice hashservice = new Defaulthashservice (); Default Algorithm SHA-512
  2. Hashservice.sethashalgorithmname ("SHA-512");
  3. Hashservice.setprivatesalt (New Simplebytesource ("123")); Private Salt, default None
  4. Hashservice.setgeneratepublicsalt (TRUE);//whether to generate a male salt, default false
  5. Hashservice.setrandomnumbergenerator (New Securerandomnumbergenerator ());//used to generate a male salt. This is the default.
  6. Hashservice.sethashiterations (1); Number of iterations to generate hash value
  7. Hashrequest request = new Hashrequest.builder ()
  8. . Setalgorithmname ("MD5"). SetSource (ByteSource.Util.bytes ("Hello"))
  9. . Setsalt (ByteSource.Util.bytes ("123")). Setiterations (2). build ();
  10. String hex = hashservice.computehash (Request). Tohex ();

1, first create a defaulthashservice, default use SHA-512 algorithm;

2, the algorithm can be modified by Hashalgorithmname property;

3, can be set by privatesalt a private salt, which in the hash automatically with the user incoming male salt mixed to produce a new salt;

4, can be through the Generatepublicsalt attribute in the case of the user does not pass the public salt, whether the production of public salt;

5, can be set randomnumbergenerator for the production of male salt;

6, you can set the Hashiterations property to modify the default number of encryption iterations;

7, need to build a hashrequest, incoming algorithm, data, public salt, the number of iterations.

Securerandomnumbergenerator is used to generate a random number:

Java code
    1. Securerandomnumbergenerator RandomNumberGenerator =
    2. New Securerandomnumbergenerator ();
    3. Randomnumbergenerator.setseed ("123". GetBytes ());
    4. String hex = randomnumbergenerator.nextbytes (). Tohex ();

5.3 Encryption/decryption

Shiro also provides support for symmetric encryption/decryption algorithms, such as AES, Blowfish, etc., and currently does not provide support for asymmetric encryption/decryption algorithms, which may be available in future versions.

AES Algorithm implementation:

Java code
    1. Aescipherservice aescipherservice = new Aescipherservice ();
    2. Aescipherservice.setkeysize (128); Set Key length
    3. Generate key
    4. Key key = Aescipherservice.generatenewkey ();
    5. String text = "Hello";
    6. Encryption
    7. String Encrpttext =
    8. Aescipherservice.encrypt (Text.getbytes (), key.getencoded ()). Tohex ();
    9. Decrypt
    10. String Text2 =
    11. New String (Aescipherservice.decrypt (Hex.decode (Encrpttext), key.getencoded ()). GetBytes ());
    12. Assert.assertequals (text, text2);

For more algorithms, refer to Example Com.github.zhangkaitao.shiro.chapter5.hash.CodecAndCryptoTest.

5.4 Passwordservice/credentialsmatcher

Shiro provides Passwordservice and credentialsmatcher to provide cryptographic password and authentication password services.

Java code
    1. Public interface Passwordservice {
    2. Enter plaintext password to get ciphertext password
    3. String Encryptpassword (Object plaintextpassword) throws IllegalArgumentException;
    4. }
Java code
    1. Public interface Credentialsmatcher {
    2. Voucher (unencrypted) matching user input token (unencrypted) with system-provided credentials (encrypted)
    3. Boolean Docredentialsmatch (Authenticationtoken token, authenticationinfo info);
    4. }

Shiro Passwordservice implementation is provided by default Defaultpasswordservice ; Credentialsmatcher implements Passwordmatcher and Hashedcredentialsmatcher (more powerful).

Defaultpasswordservice with Passwordmatcher implement a simple password encryption and authentication Service

1. Define Realm (Com.github.zhangkaitao.shiro.chapter5.hash.realm.MyRealm)

Java code
  1. public class Myrealm extends Authorizingrealm {
  2. Private Passwordservice Passwordservice;
  3. public void Setpasswordservice (Passwordservice passwordservice) {
  4. This.passwordservice = Passwordservice;
  5. }
  6. Omit Dogetauthorizationinfo, see the code specifically
  7. @Override
  8. Protected AuthenticationInfo Dogetauthenticationinfo (Authenticationtoken token) throws Authenticationexception {
  9. return new Simpleauthenticationinfo (
  10. "WU",
  11. Passwordservice.encryptpassword ("123"),
  12. GetName ());
  13. }
  14. }

For convenience, direct injection of a passwordservice to encrypt the password, the actual use of the service layer with the use of Passwordservice encryption password and coexistence to the database.

2. INI configuration (shiro-passwordservice.ini)

Java code
  1. [Main]
  2. Passwordservice=org.apache.shiro.authc.credential.defaultpasswordservice
  3. Hashservice=org.apache.shiro.crypto.hash.defaulthashservice
  4. Passwordservice.hashservice= $hashService
  5. Hashformat=org.apache.shiro.crypto.hash.format.shiro1cryptformat
  6. passwordservice.hashformat= $hashFormat
  7. Hashformatfactory=org.apache.shiro.crypto.hash.format.defaulthashformatfactory
  8. passwordservice.hashformatfactory= $hashFormatFactory
  9. Passwordmatcher=org.apache.shiro.authc.credential.passwordmatcher
  10. Passwordmatcher.passwordservice= $passwordService
  11. Myrealm=com.github.zhangkaitao.shiro.chapter5.hash.realm.myrealm
  12. Myrealm.passwordservice= $passwordService
  13. Myrealm.credentialsmatcher= $passwordMatcher
  14. securitymanager.realms= $myRealm

2.1, Passwordservice use Defaultpasswordservice, if necessary can also be customized;

2.2, Hashservice define hash password used Hashservice, default use Defaulthashservice (default SHA-256 algorithm);

2.3, Hashformat used to format the hashed values, the default use of Shiro1cryptformat, in addition to provide Base64format and Hexformat, For a password with salt, customize the implementation Parsablehashformat and then format the salt into the hash value;

2.4. Hashformatfactory is used to hash the password and salt according to the hashes; because if you use the SHA algorithm, a salt is generated that needs to be saved to the hash value so that it is used when compared to the incoming password ; Defaulthashformatfactory is used by default;

2.5, Passwordmatcher use Passwordmatcher, it is a credentialsmatcher realization;

2.6, the Credentialsmatcher assignment to Myrealm,myrealm indirectly inherited Authenticatingrealm, After it has called the Getauthenticationinfo method to obtain the AuthenticationInfo information, it uses Credentialsmatcher to verify that the credentials match. Throws a Incorrectcredentialsexception exception if it does not match.

3, the test case please refer to com.github.zhangkaitao.shiro.chapter5.hash.PasswordTest.

You can also refer to configuration Shiro-jdbc-passwordservice.ini, which provides jdbcrealm test cases, call Sql/shiro-init-data.sql to initialize user data before testing.

The disadvantage of the above method is that the salt is in the hash value, there is no implementation such as the password retry limit.

Hashedcredentialsmatcher Implementing Password Authentication Services

Shiro provides a credentialsmatcher hash implementation hashedcredentialsmatcher, unlike the previous passwordmatcher, which is used only for password authentication and can provide its own salts instead of randomly generating salts, And the algorithm that generates the hash value of the password needs to write itself, because it can provide its own salt.

1 , generating a password hash value

Here we use the MD5 algorithm, "Password + salt (user name + random number)" way to generate hash values:

Java code
    1. String algorithmname = "MD5";
    2. String username = "Liu";
    3. String Password = "123";
    4. String SALT1 = Username;
    5. String salt2 = new Securerandomnumbergenerator (). Nextbytes (). Tohex ();
    6. int hashiterations = 2;
    7. Simplehash hash = new Simplehash (algorithmname, password, SALT1 + salt2, hashiterations);
    8. String Encodedpassword = Hash.tohex ();

If you want to write a user module, you need to save the password with the above algorithm when adding a user/reset password, the generated password and salt2 are stored in the database (because our hashing algorithm is: MD5 (MD5 (password +username+salt2)).


Java code
    1. Protected authenticationinfo dogetauthenticationinfo ( Authenticationtoken token)  throws authenticationexception {  
    2.      String username =  "Liu";  //user name and salt1  
    3.      String password =  "202cb962ac59075b964b07152d234b70";  //Password after encryption   
    4.     String salt2 =  "202cb962ac59075b964b07152d234b70";  
    5. simpleauthenticationinfo ai =   
    6.          new simpleauthenticationinfo (Username, password, getname ());   
    7.     ai.setcredentialssalt (ByteSource.Util.bytes (USERNAME+SALT2));  //Salt is user name + random number   
    8.         return ai;  
    9. }    

This is to assemble the corresponding data generated in step 1 into Simpleauthenticationinfo, set the salt through the Simpleauthenticationinfo Credentialssalt, Hashedcredentialsmatcher will automatically recognize this salt.

If you use Jdbcrealm, you need to modify the SQL that gets the user information (including salt): "Select Password, password_salt from users where username =?" While our salt is made by username+ Password_salt is composed, so it needs to be modified by the following INI configuration (shiro-jdbc-hashedcredentialsmatcher.ini):

Java code
    1. Jdbcrealm.saltstyle=column
    2. Jdbcrealm.authenticationquery=select password, concat (Username,password_salt) from users where username =?
    3. Jdbcrealm.credentialsmatcher= $credentialsMatcher

1, saltstyle means the use of password + salt mechanism, authenticationquery the first column is the password, the second column is salt;

2, through the Authenticationquery designated password and salt query SQL;

It is also important to note that Shiro uses Apache Commons Beanutils by default and does not convert enum type by default, so you need to register an enum converter "beanutilsbean.getinstance () yourself. Getconvertutils (). Register (new Enumconverter (), JdbcRealm.SaltStyle.class); " Please refer to the code in the example "Com.github.zhangkaitao.shiro.chapter5.hash.PasswordTest" for details.

You can also refer to configuration Shiro-jdbc-passwordservice.ini, which provides jdbcrealm test cases, call Sql/shiro-init-data.sql to initialize user data before testing.

3. INI configuration (shiro-hashedcredentialsmatcher.ini)

Java code
    1. [Main]
    2. Credentialsmatcher=org.apache.shiro.authc.credential.hashedcredentialsmatcher
    3. Credentialsmatcher.hashalgorithmname=md5
    4. credentialsmatcher.hashiterations=2
    5. Credentialsmatcher.storedcredentialshexencoded=true
    6. Myrealm=com.github.zhangkaitao.shiro.chapter5.hash.realm.myrealm2
    7. Myrealm.credentialsmatcher= $credentialsMatcher
    8. securitymanager.realms= $myRealm

1, through the CREDENTIALSMATCHER.HASHALGORITHMNAME=MD5 specified hash algorithm for MD5, need and generate password when the same;

2, credentialsmatcher.hashiterations=2, the number of hash iterations, the need and the meaning of generating passwords;

3, Credentialsmatcher.storedcredentialshexencoded=true indicates whether to store the hash after the password is 16, the need and generate the password, the default is base64;

The most important thing to note here is that the hashedcredentialsmatcher algorithm needs to be the same as the algorithm that generated the password. In addition, Hashedcredentialsmatcher will automatically obtain Credentialssalt salts based on whether the type of AuthenticationInfo is saltedauthenticationinfo.

4, the test case please refer to com.github.zhangkaitao.shiro.chapter5.hash.PasswordTest.

Password Retry attempts limit

If the password is up to 5 retries in 1 hours, if the number of attempts more than 5 times to lock 1 hours, 1 hours can be retried again, if the retry failed, can be locked for 1 days, and so on, to prevent the password is brute force. We use Ehcache to record the number of retries and time-outs by inheriting Hashedcredentialsmatcher.


Java code
  1. public boolean Docredentialsmatch (Authenticationtoken token, AuthenticationInfo info) {
  2. String username = (string) token.getprincipal ();
  3. Retry Count + 1
  4. Element element = Passwordretrycache.get (username);
  5. if (element = = null) {
  6. element = new Element (username, new Atomicinteger (0));
  7. Passwordretrycache.put (Element);
  8. }
  9. Atomicinteger RetryCount = (Atomicinteger) element.getobjectvalue ();
  10. if (Retrycount.incrementandget () > 5) {
  11. If retry count > 5 throw
  12. throw new Excessiveattemptsexception ();
  13. }
  14. Boolean matches = Super.docredentialsmatch (token, info);
  15. if (matches) {
  16. Clear Retry Count
  17. Passwordretrycache.remove (username);
  18. }
  19. return matches;
  20. }

As the code logic is relatively simple, that is, if the password input correctly clears the cache record, otherwise the cache retries +1, if more than 5 times the throw exception indicates the number of retries exceeded.

Spring/shiro technology can be explored Dabigatran 247221261. Group has the relevant sample code, you are welcome to discuss learning ~

Fifth chapter code/Encryption--"Follow me to learn Shiro"

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

Tags Index: