Project code comes from:
12-Shiro and Springboot integration_bilibili_bilibili
Follow the Shang Silicon Valley WeChat public account and enter the shiro system to return the download link (the Baidu network disk link contains code and handouts):
The database table creation statement is in the handout, and you need to add test user data yourself.
The project is only suitable for learning testing, set two breakpoints:
1. Subject.login(token) around line 44 in ../controller/MyController.java;
/* com/atguigu/shiro/controller/MyController.java file */ @Controller @RequestMapping("myController") public class MyController { @GetMapping("userLogin") @ResponseBody public String userLogin(String name, String pwd, @RequestParam(defaultValue = "false")boolean rememberMe, HttpSession session){ try { subject.login(token); //Breakpoint 1 //return "Login successful"; session.setAttribute("user",token.getPrincipal().toString()); return "main"; } catch (AuthenticationException e) { e.printStackTrace(); System.out.println("Login failed"); return "Login failed"; } }
2. In the doGetAuthenticationInfo() method after line 46 in ../realm/MyRealm.java
/* In the doGetAuthenticationInfo() method in com/atguigu/shiro/realm/MyRealm.java*/ @Component public class MyRealm extends AuthorizingRealm { //Customize login authentication method @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //1 Get user identity information String name = authenticationToken.getPrincipal().toString(); //Breakpoint 2 //2 Call the business layer to obtain user information (database) User user = userService.getUserInfoByName(name); //3 Non-empty judgment, encapsulate the data and return it if(user !=null){ AuthenticationInfo info = new SimpleAuthenticationInfo( authenticationToken.getPrincipal(), user.getPwd(), ByteSource.Util.bytes("salt"), authenticationToken.getPrincipal().toString() ); return info; } return null; } }
debug operation, call the interface http://localhost:8080/myController/userLogin?name=Zhang Shan &pwd=123456
The program running process goes through:
1. com.atguigu.shiro.controller.MyController#userLogin(java.lang.String, java.lang.String, boolean, javax.servlet.http.HttpSession), carrying parameter token
2. org.apache.shiro.subject.support.DelegatingSubject#login, carrying parameter token
3. org.apache.shiro.mgt.DefaultSecurityManager#login, carrying parameter token
4. org.apache.shiro.mgt.AuthenticatingSecurityManager#authenticate, carrying parameter token
5. org.apache.shiro.authc.AbstractAuthenticator#authenticate, carrying parameter token
6. org.apache.shiro.authc.pam.ModularRealmAuthenticator#doAuthenticate, there are two parameters passed to the next level, namely Realm object and authenticationToken.
The Realm object is our customized com.atguigu.shiro.realm.MyRealm
7. org.apache.shiro.authc.pam.ModularRealmAuthenticator#doSingleRealmAuthentication. Call realm.getAuthenticationInfo(token) here to verify whether the username and password in the token are legal (usually compared with the username and password in the database) , if the comparison is consistent, it is legal)
8. org.apache.shiro.realm.AuthenticatingRealm#getAuthenticationInfo
9. org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo
The specific implementation is: com.atguigu.shiro.realm.MyRealm#doGetAuthenticationInfo
From the inheritance diagram, the Bean object defaultWebSecurityManager() in the project com.atguigu.shiro.config.ShiroConfig configuration shows that the customized DefaultWebSecurityManager is a subclass of Article 4 AuthenticatingSecurityManager.
@Bean public DefaultWebSecurityManager defaultWebSecurityManager(){ //1Create defaultWebSecurityManager object DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); //2Create an encrypted object and set related properties HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(); //2.1 uses md5 encryption matcher.setHashAlgorithmName("md5"); //2.2 Number of iteration encryption times matcher.setHashIterations(3); //3 Store the encrypted object into myRealm myRealm.setCredentialsMatcher(matcher); //4Save myRealm into the defaultWebSecurityManager object defaultWebSecurityManager.setRealm(myRealm); //4.5Set rememberMe defaultWebSecurityManager.setRememberMeManager(rememberMeManager()); //4.6 Set cache manager defaultWebSecurityManager.setCacheManager(getEhCacheManager()); //5return return defaultWebSecurityManager; }
The three methods used in configuration: setRealm(), setRememberMeManager(), and setCacheManager() are all defined in the parent class. //4Save myRealm into the defaultWebSecurityManager object defaultWebSecurityManager.setRealm(myRealm); //4.5Set rememberMe defaultWebSecurityManager.setRememberMeManager(rememberMeManager()); //4.6 Set cache manager defaultWebSecurityManager.setCacheManager(getEhCacheManager());
Therefore, in shiro’s username and password verification process, when calling AuthenticatingSecurityManager#authenticate, shiro can find the implementation object defaultWebSecurityManager and its configured realm object myRealm based on the inheritance relationship, and execute the method of myRealm.