shiro encryption operation
Hash algorithm is generally used to generate summary information of data. It is an irreversible algorithm, which is generally suitable for storing data such as passwords, and common hash legal persons such as MD5 and SHA. In general, it is better to provide a salt for hash algorithm, such as encrypted password (admin). The hash value generated is "21232f9757a837dasdadw", which can reach some MD5
It's easy to decrypt the website by hashing the value to "admin", that is, it's easier to directly hash the password. At this time, we can add some interference data, such as user name and ID. The hash object is "password + user name + ID". The hash value generated in this way is relatively more difficult to crack.
Steps: 1. After custom encryption, realm: Rewrite three methods: getName, doGetAuthorizationInfo and doGetAuthenticationInfo
Structure chart:
pom file:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.study</groupId> <artifactId>shiro</artifactId> <version>1.0-SNAPSHOT</version> <name>shiro</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.2</version> </dependency> </dependencies> <build> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle --> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-jar-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle --> <plugin> <artifactId>maven-site-plugin</artifactId> <version>3.7.1</version> </plugin> <plugin> <artifactId>maven-project-info-reports-plugin</artifactId> <version>3.0.0</version> </plugin> </plugins> </pluginManagement> </build> </project>
package com.study.shiro.realm; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; public class PasswordRealm extends AuthorizingRealm { @Override public String getName() { return "PasswordRealm"; } /** * To grant authorization * @param principals * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { return null; } /** * Authentication * @param token * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // Search user information through user name, encapsulate it into an AuthenticationInfo object and return it, which is convenient for the authenticator to compare // Get user name in token String username = (String) token.getPrincipal(); // Query the database by user name, and find out the corresponding information of the user: account, password String dbUsername = "zhangsan"; if(!dbUsername.equals(username)){ return null; } // Password 666 + account + hash times after encryption saved in simulation database 3 times String password = "cd757bae8bd31da92c6b14c235668091"; // info object indicates the login comparison information of realm: parameter 1 user information, parameter 2, password, parameter 3 salt, parameter 4 name of current realm SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, ByteSource.Util.bytes(dbUsername), getName()); return simpleAuthenticationInfo; } }
INI file shiro-cryptography.ini
[main] #Define credential matcher credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher #Hash algorithm credentialsMatcher.hashAlgorithmName=md5 #Hash times credentialsMatcher.hashIterations=3 #Set credential matcher to realm myRealm=com.study.shiro.realm.PasswordRealm myRealm.credentialsMatcher=$credentialsMatcher securityManager.realms=$myRealm
Test method:
@Test public void testLoginByPasswordRealm() throws Exception{ // 1. Create the SecurityManager factory object, load the configuration file, and create Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-cryptography.ini"); // 2. Create a Securitymanage object through the factory object SecurityManager securityManager = factory.getInstance(); // 3. Bind the securitymanage to the current running environment, so that the system can access the securityManager object anytime, anywhere SecurityUtils.setSecurityManager(securityManager); // 4: create the currently logged in principal. Note that the principal is not authenticated at this time Subject subject = SecurityUtils.getSubject(); // 5: bind the identity and credentials of the principal login, i.e. account password UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","666"); try { // 6. Principal login subject.login(token); }catch (IncorrectCredentialsException incorrectCredentialsException){ System.out.println("Wrong password!"); }catch (UnknownAccountException UnknownAccountException){ System.out.println("User name error!"); } // 7: judge whether the login is successful System.out.println("Verify login 1:" + subject.isAuthenticated()); // 8: logout subject.logout(); System.out.println("Verify login 2:" + subject.isAuthenticated()); }