summary
In the last blog, we mainly talked about custom Realm. The passwords used for user authentication are in clear text. This method is not desirable. Often, in our actual combat development, the user's passwords are stored in ciphertext, and the encryption algorithm is required to be irreversible. The famous encryption algorithms include MD5, SHA1, etc. So in this blog, we mainly introduce Shiro security framework and learn its encryption scheme. Here we use MD5 encryption, and then. MD5 encryption is divided into adding salt and not adding salt.
No salt certification
@Test public void testMatcher() { CustomRealm customRealm = new CustomRealm(); //1. Build a SecurityManager environment DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); //Set Realm defaultSecurityManager.setRealm(customRealm); SecurityUtils.setSecurityManager(defaultSecurityManager); //Get principal Subject subject = SecurityUtils.getSubject(); //token of user name and password UsernamePasswordToken token = new UsernamePasswordToken("dev", "123456"); try { //2. The subject submits an authentication request subject.login(token); System.out.println("Whether authority authentication: isAuthenticated=" + subject.isAuthenticated()); //Check for roles subject.checkRoles("admin"); System.out.println("yes admin role"); //Check for permissions subject.checkPermissions("user:delete", "user:edit", "user:list", "user:add"); System.out.println("yes user:add,user:list,user:edit,user:delete jurisdiction"); } catch (IncorrectCredentialsException exception) { System.out.println("Wrong user name or password"); } catch (LockedAccountException exception) { System.out.println("Account locked"); } catch (DisabledAccountException exception) { System.out.println("Account has been disabled"); } catch (UnknownAccountException exception) { System.out.println("user does not exist"); } catch (UnauthorizedException ae) { System.out.println("User does not have permission"); } }
CustomRealm please refer to Spring Boot uses custom Realm for authentication and authorization (V)
Add password authentication core code
//Encrypt HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(); //md5 encryption matcher.setHashAlgorithmName("md5"); //Set encryption times matcher.setHashIterations(2); customRealm.setCredentialsMatcher(matcher);
Modify the method of obtaining ciphertext in CustomRealm
/** * Obtain ciphertext password * @Author: djy * @UpdateUser: * @Version: 0.0.1 * @param currentPassword * @return java.lang.String * @throws */ private String getPasswordMatcher(String currentPassword){ return new Md5Hash(currentPassword, null,2).toString(); }
Modify doGetAuthenticationInfo
/** * User authentication * * @param authenticationToken * @return org.apache.shiro.authc.AuthenticationInfo * @throws * @Author: djy * @UpdateUser: * @Version: 0.0.1 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("Start execution*******doGetAuthenticationInfo Method****"); //Get login user name String userName = (String) authenticationToken.getPrincipal(); //Get user information from user name to database String password = getPasswordByUsername(userName); if (null == password) { return null; } System.out.println("Password is:" + password); String matcherPwd = getPasswordMatcher(password); System.out.println(matcherPwd); SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userName, password, getName()); return authenticationInfo; }
When the user admin logs in, the program outputs
UsernamePasswordToken token = new UsernamePasswordToken("admin", "123456");
- Program output
Whether authority authentication: isAuthenticated=true Start execution*******doGetAuthorizationInfo Method**** admin yes admin role Start execution*******doGetAuthorizationInfo Method**** admin Start execution*******doGetAuthorizationInfo Method**** admin Start execution*******doGetAuthorizationInfo Method**** admin Start execution*******doGetAuthorizationInfo Method**** admin yes user:add,user:list,user:edit,user:delete jurisdiction
- If it is changed, it is still tested in clear text
// String matcherPwd=getPasswordMatcher(password); // System.out.println(matcherPwd); // SimpleAuthenticationInfo authenticationInfo = new //SimpleAuthenticationInfo(username,matcherPwd,getName()); SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,getName());
- Program output
Start execution*******doGetAuthenticationInfo Method**** Password: 123456 4280d89a5a03f812751f504cc10ee8a5 Wrong user name or password
Salt certification
When the passwords of two users are the same, simply using MD5 encryption without salt will find that there are passwords with the same structure in the database, which is also unsafe. We hope that even if the original passwords of two people are the same, the encrypted results will be different. How? In fact, it's like cooking. Two courses of fish flavored shredded pork with different salt make it taste different. The same is true for MD5 encryption, which requires salt value encryption.
Create testSaltMatcher method
@Test public void testSaltMatcher() { CustomRealm customRealm = new CustomRealm(); //Encrypt HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(); //mdf encryption matcher.setHashAlgorithmName("md5"); //Set encryption times matcher.setHashIterations(1); customRealm.setCredentialsMatcher(matcher); //1. Build a SecurityManager environment DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); //Set Realm defaultSecurityManager.setRealm(customRealm); SecurityUtils.setSecurityManager(defaultSecurityManager); //Get principal Subject subject = SecurityUtils.getSubject(); //token of user name and password UsernamePasswordToken token = new UsernamePasswordToken("admin", "123456"); try { //2. The subject submits an authentication request subject.login(token); System.out.println("Whether authority authentication: isAuthenticated=" + subject.isAuthenticated()); //Check for roles subject.checkRoles("admin"); System.out.println("yes admin role"); //Check for permissions subject.checkPermissions("user:delete", "user:edit", "user:list", "user:add"); System.out.println("yes user:add,user:list,user:edit,user:delete jurisdiction"); //if no exception, that's it, we're done! } catch (IncorrectCredentialsException exception) { System.out.println("Wrong user name or password"); } catch (LockedAccountException exception) { System.out.println("Account locked"); } catch (DisabledAccountException exception) { System.out.println("Account has been disabled"); } catch (UnknownAccountException exception) { System.out.println("user does not exist"); } catch (UnauthorizedException ae) { System.out.println("User does not have permission"); } }
Salt verification core code
//Set the value of the salt authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(username));
Modify CustomRealm and add a method to obtain salt ciphertext
/** * Obtain ciphertext password * * @param currentPassword * @return java.lang.String * @throws * @Author: djy * @UpdateUser: * @Version: 0.0.1 */ private String getPasswordMatcher(String currentPassword, String username) { return new Md5Hash(currentPassword, username).toString(); }
Modify doGetAuthenticationInfo
/** * User authentication * * @param authenticationToken * @return org.apache.shiro.authc.AuthenticationInfo * @throws * @Author: djy * @UpdateUser: * @Version: 0.0.1 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("Start execution*******doGetAuthenticationInfo Method****"); //Get login user name String userName = (String) authenticationToken.getPrincipal(); //Get user information from user name to database String password = getPasswordByUsername(userName); if (null == password) { return null; } // System.out.println("password is:" + password); // String matcherPwd = getPasswordMatcher(password); String matcherPwd = getPasswordMatcher(password,userName); System.out.println(matcherPwd); SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userName, matcherPwd, getName()); //Set the value of the salt authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(userName)); return authenticationInfo; }
test
- When the user admin logs in, the program outputs
UsernamePasswordToken token = new UsernamePasswordToken("admin", "123456");
Start execution*******doGetAuthenticationInfo Method**** a66abb5684c45962d887564f08346e8d Whether authority authentication: isAuthenticated=true Start execution*******doGetAuthorizationInfo Method**** admin yes admin role Start execution*******doGetAuthorizationInfo Method**** admin Start execution*******doGetAuthorizationInfo Method**** admin Start execution*******doGetAuthorizationInfo Method**** admin Start execution*******doGetAuthorizationInfo Method**** admin yes user:add,user:list,user:edit,user:delete jurisdiction
- When the user admin logs in, but the password is input into 1234567 program output
UsernamePasswordToken token = new UsernamePasswordToken("admin", "1234567");
Start execution*******doGetAuthenticationInfo Method**** a66abb5684c45962d887564f08346e8d Wrong user name or password
- When the user admin logs in, the password is also entered correctly, but the plaintext program output is used for authentication
//Comment out the following two methods //String matcherPwd = getPasswordMatcher(password,userName); //System.out.println(matcherPwd); SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,getName());
Start execution*******doGetAuthenticationInfo Method**** Wrong user name or password
shiro encryption is all about here. In fact, some small partners will have questions. If our company uses sessionID as the login status certificate, what should we do and how can we make users pass authentication? Here, we can customize the password matching class, inherit the HashedCredentialsMatcher class, and override its doCredentialsMatch (password matching method). Later, when we explain the actual combat development, we will explain it in detail.