shiro验证用户名密码的内部流程

 项目代码来自: 

12-Shiro与Springboot整合_哔哩哔哩_bilibili

关注尚硅谷微信公众号 ,输入shiro系统返回下载链接(百度网盘链接中含代码和讲义):

shiro验证用户名密码的内部流程_第1张图片

数据库建表语句在讲义中,需自行添加测试用户数据。

项目仅适合学习测试,设置两个断点:

1、../controller/MyController.java中的44行左右subject.login(token);

/*  com/atguigu/shiro/controller/MyController.java 文件 */

@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);  //断点1
            //return "登录成功";
            session.setAttribute("user",token.getPrincipal().toString());
            return "main";

        } catch (AuthenticationException e) {
            e.printStackTrace();
            System.out.println("登录失败");
            return "登录失败";
        }

    }

 2、../realm/MyRealm.java中第46行以后的doGetAuthenticationInfo()方法内

/* com/atguigu/shiro/realm/MyRealm.java 中的doGetAuthenticationInfo()方法内*/

@Component
public class MyRealm extends AuthorizingRealm {


    //自定义登录认证方法
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1获取用户身份信息
        String name = authenticationToken.getPrincipal().toString(); //断点2
        //2调用业务层获取用户信息(数据库)
        User user = userService.getUserInfoByName(name);
        //3非空判断,将数据封装返回
        if(user !=null){
            AuthenticationInfo info = new SimpleAuthenticationInfo(
                    authenticationToken.getPrincipal(),
                    user.getPwd(),
                    ByteSource.Util.bytes("salt"),
                    authenticationToken.getPrincipal().toString()
            );
            return info;
        }
        return null;
    }
}

debug运行,调用接口http://localhost:8080/myController/userLogin?name=张山&pwd=123456

shiro验证用户名密码的内部流程_第2张图片

程序运行过程依次经过:

 1、com.atguigu.shiro.controller.MyController#userLogin(java.lang.String, java.lang.String, boolean, javax.servlet.http.HttpSession),携带参数token

shiro验证用户名密码的内部流程_第3张图片

2、org.apache.shiro.subject.support.DelegatingSubject#login,携带参数token

shiro验证用户名密码的内部流程_第4张图片

3、org.apache.shiro.mgt.DefaultSecurityManager#login,携带参数token

shiro验证用户名密码的内部流程_第5张图片

4、org.apache.shiro.mgt.AuthenticatingSecurityManager#authenticate,携带参数token

shiro验证用户名密码的内部流程_第6张图片

5、org.apache.shiro.authc.AbstractAuthenticator#authenticate,携带参数token

shiro验证用户名密码的内部流程_第7张图片

6、org.apache.shiro.authc.pam.ModularRealmAuthenticator#doAuthenticate,传给下一级的参数有2个,分别是Realm对象和authenticationToken。

Realm对象是我们自定义的com.atguigu.shiro.realm.MyRealm

shiro验证用户名密码的内部流程_第8张图片

7、org.apache.shiro.authc.pam.ModularRealmAuthenticator#doSingleRealmAuthentication,到这里调用realm.getAuthenticationInfo(token),才开始验证token中的用户名密码是否合法(一般是与数据库中的用户名密码进行比对,比对一致为合法)

shiro验证用户名密码的内部流程_第9张图片

8、org.apache.shiro.realm.AuthenticatingRealm#getAuthenticationInfo

shiro验证用户名密码的内部流程_第10张图片

9、org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo

具体实现为:com.atguigu.shiro.realm.MyRealm#doGetAuthenticationInfo

shiro验证用户名密码的内部流程_第11张图片

shiro验证用户名密码的内部流程_第12张图片

 

项目com.atguigu.shiro.config.ShiroConfig配置中的Bean对象defaultWebSecurityManager()从继承关系图谱上看,自定义的DefaultWebSecurityManager是第4条AuthenticatingSecurityManager的子类。

    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(){
        //1创建defaultWebSecurityManager 对象
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        //2创建加密对象,设置相关属性
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        //2.1采用md5加密
        matcher.setHashAlgorithmName("md5");
        //2.2迭代加密次数
        matcher.setHashIterations(3);
        //3将加密对象存储到myRealm中
        myRealm.setCredentialsMatcher(matcher);
        //4将myRealm存入defaultWebSecurityManager 对象
        defaultWebSecurityManager.setRealm(myRealm);
        //4.5设置rememberMe
        defaultWebSecurityManager.setRememberMeManager(rememberMeManager());
        //4.6设置缓存管理器
        defaultWebSecurityManager.setCacheManager(getEhCacheManager());

        //5返回
        return defaultWebSecurityManager;
    }
在配置中使用的3个方法:setRealm()、setRememberMeManager()、setCacheManager()都在父类中有定义。
//4将myRealm存入defaultWebSecurityManager 对象
defaultWebSecurityManager.setRealm(myRealm);
//4.5设置rememberMe
defaultWebSecurityManager.setRememberMeManager(rememberMeManager());
//4.6设置缓存管理器
defaultWebSecurityManager.setCacheManager(getEhCacheManager());

shiro验证用户名密码的内部流程_第13张图片

所以在shiro验证用户名密码流程中,调用 AuthenticatingSecurityManager#authenticate时,shiro才能根据继承关系,找到实现对象defaultWebSecurityManager以及其配置的realm对象myRealm,执行myRealm的方法。

你可能感兴趣的:(spring,java,后端)