(3)shiro架构图之整合redis理论

在没有使用shiro框架做认证的时候,我们使用最原始方法做认证,就是在数据库中新建一张表格,存储有account和password,然后用户通过表单提交账号和密码,在登录接口中去进行比对。其实在shiro中也是一样的。总之都是要进行数据比对的,只不过shiro框架中为了安全以及认证效率等方面,在这个基础上附加了一些更多的功能,那么我下面就带大家来看看shiro的整个认证过程。

  • 操作session的流程以及session的基本底层数据结构

在这里插入图片描述
我们来看看这个this.resolveSession(context)这个方法的作用就是将session放入到SubjectContext中,那我们首先肯定是要去获取到这个Session,这个session是存储在一个Map<String,Session>中的,所以我们现在就是先要去得到Map中的Key,也就是SessionKey(是sessionId,request,response)的包装。
在这里插入图片描述
在这里插入图片描述
首先会去创建一个SessionKey,在这里创建了SessionKey的子类对象,构造器中传入sessionId,request,response这三个参数,但其实sessionId目前是null(因为SubjectContext中不存在,参考SubjectContext创建过程),但是我们又需要这个值去Map中检索Session,所以我们下一步去获取到这个sessionId
在这里插入图片描述
会通过两种方式来获取这个sessionId:①通过cookie②通过名称为JSESSIONID的参数值

在这里插入图片描述
我们可以看到是使用sessionDao的readSession(id)方法去获取的
在这里插入图片描述
我们在配置文件中通常会配置一个SecurityManage的子类对象,其继承的父类SessionSecurityManage中有一个属性DefaultSessionManager,这个就是我们在没有配置session管理器使用的默认session管理器
在这里插入图片描述
这个默认的session管理器主要作用就是用来管理session的。比如使用sessionFactory来创建session对象,使用sessionDao来去对这个创建了的session对象进行持久方面的操作,具体这个Session对象存放在哪里,由sessionDao说了算
在这里插入图片描述
从名称我们就知道,我们默认使用的是MemorySessionDao,其中有个Map,很明显就是将Session存放在当前的JVM的内存中的
在这里插入图片描述

SessionDao的其中一个接口就是readSession,在这个方法中会调用doReadSession,这是个抽象方法,具体操作留给子类去实现
在这里插入图片描述
所以我想,上面使用sessionDao调用readSession方法,应该知道具体就是根据sessionId到这个Map中去检索的

  • 什么时候创建session
    其实在你第一次访问系统的,你的sessionId是不存在的,或者说是一个错误的sessionId,其实这个 时候是获取不到session的,第一次获取session将会返回null

在这里插入图片描述
在这里插入图片描述
我发送了一个登陆的请求,我们通过debug可以看到是存在sessionId的,但是获取不到session,因为我重启了服务,所以存在内存中的session(MemorySessionDao)就消失了,但是为什么会存在
sessionId,因为从上面我们知道这个sessionId是从cookie中获取到的,我没有清除cookie,所以服务端可以读取到。

在这里插入图片描述
创建Subject这个对象完成后,我们可以看到,里面并没有一些重要的信息。比如principals,authenticated,session.这三个信息非常重要,principals是权限的信息,authenticated是标志是否已经做过认证,session存储所有的重要信息。比如在athu这个拦截器中,直接就是调用Subect的方法()去做校验。

在这里插入图片描述
校验信息是通过我们自己获取当前绑定线程的Subject的login()方法的时候放入到Subject这个对象中的,我们想想,shiro也不知道什么时候,在哪里去,怎样做认证,只有我们在登录接口自己去手动调用登录接口,然后shiro再根据我们校验的情况,去放入这些信息到Subject中

在这里插入图片描述
在login方法中,如果认证过程中抛出异常,那么将表示认证失败,不可能会有机会在login方法中去调用createSubject方法的,所以能往下执行,说明是认证成功的,然后使用token,info,subject去创建SubjectContext
在这里插入图片描述
在创建Subject之前,还是先创建SubjectContext(上下文),只不过和之前上下文不一样,这次包含了权限信息,认证信息标记(不存放认证具体信息),当前的subject对象
在这里插入图片描述
这段代码是不是很熟悉,确实是和之前是同一段代码,不过上下文有四个信息,info,token,authc标记,还有就是当前的subject对象,根据上下文创建问Subject对象后,就会调用save方法,将创建的Subject信息保存到session,其实最终都是为了将信息保存到session当中,然后在构建Subject过程根据保存的session,恢复回原来的Subject对象

在这里插入图片描述
有没有看到merge这个关键参数,其实就是合并的意思,应该我们在使用svn和git开发用的特别多,这里就是将Subject中的权限信息和认证标志合并到已经创建的session中,当然这里还没有创建session
在这里插入图片描述
在这里插入图片描述
这就是合并权限的代码,因为是做登录操作,肯定是第一次,所以就会在这个地方创建session,放入到Map<String,Session>中,然后将权限信息放入到session中。
在这里插入图片描述

这里同样是将认证通过的一个true值放入到Session中
在这里插入图片描述

这里就是执行完save方法之后,Subject对象的各个属性情况,同时这些信息也被保留在session中,如果客户端下回再请求,那么就用session中的信息来恢复Subject对象,然后在过滤器中使用subject对象进行校验拦截

在这里插入图片描述

总结:从上面我们可以看到,其实就是对session的一个增,删,改,查操作,所有的认证校验都和session关联,所以如果我们想要将session保存在redis中,其实只要在配置SessionManage的时候,不使用默认的MemorySessionDao,我们自己去实现一个SessionDao,然后配置的时候将我们自己定义的Sessiondao注入即可。具体实现,将在下一个博客,这编是原理性的指导。

猜你喜欢

转载自blog.csdn.net/weixin_38312719/article/details/89023256
今日推荐