(2)shiro架构图之Subject的构建过程

转载注明出处:https://blog.csdn.net/weixin_38312719/article/details/88412606

  • 用过shiro的人都知道,对于我们开发人员来说,都是和Subject这个对象来打交道的,所以我们要对于Subject这个接口进行深入的了解。但是这里我们主要讲解Subject这个对象里面各个属性值的赋值过程,因为后面使用Subject.isAuthenticated()这个方法来判断是否当前认证主体是否经过认证,在isAuthenticated()方法中其实就是判断Subject对象的boolean authenticated这个属性的值,在shiro中所有需要认证用到的信息都可以通过Subject属性值来进行判断和获取,所以我们知道了解Subject这个对象各个属性值的含义以及用处,那么我们就可以掌握shiro的使用了。

  • 因为Subject是一个接口,不存在属性的说法,这里说的属性主要是说他的实现类,比如我们常用的WebDelegatingSubject,常用的属性如下:

    1. SecurityManager securityManager
    2. Session session
    3. String host
    4. boolean authenticated
    5. PrincipalCollection principals
    6. ServletRequest servletRequest
    7. ServletResponse servletResponse

我们想要构造一个Subject对象,那么肯定需要有构建的条件,那么在shiro中,有一个SubjectContext这样的对象,又称作Subject上下文,即根据Subject上下文来构建Subject的,Subject里面所有的属性值都在SubjectContext中,所以我们先要来看看SubjectContext是怎么构建的(SubjectContext其实就是一个Map)。
在这里插入图片描述这段代码是在AbstractShiroFilter中的,这个就是我们每次都要请求经过的的代理过滤器,在每个新的亲求来的时候我们都需要构建一遍Subject对象,只是每次构建的Subject的SubjectContext里面存储的内容不一样(内容不一样,后面会讲解)

看表面意思,是不是先创建一个Builder对象,然后使用Builder对象去创建Subject,后面的BuildWebSubject()我们可以先不管,我们先看看怎么创建SubjectContext的,其实就是在创建Builder对象的时候去创建SubjectContext的。
在这里插入图片描述

在这里插入图片描述

先说明一下这两个类,这两个类是不是叫的是一样的名称,大家不必在意这些,就是类名一样,第一个类是子类,第二个类是父类。在子类的构造器中是不是调用了父类的带有SecurityManage参数的构造器,我们在父类中看到,有两个属性,一个是SecurityManage还有一个就是我们比较关心的SubjectContext,在父类构造方法中是不是创建了一个SubjectContext对象,并且把SecurityManage对象放入到Subject上下文中,我们把SubjectContext当作一个Map来看,相当于一个存放所有Subject对象所需要信息的容器。

在源码中我们看到,在创建Builder对象的时候,已经将request,response,securityManage三个对象放入SubjectContext中了,如下:

在这里插入图片描述

这样一个最基本用来创建Subject对象的SubjectContext上下文就创建好了,接下来就会使用这个Build对象来去创建Subject:
在这里插入图片描述

我们看到在Bulid类中,使用buildSubject()进行创建Subject,认证主题(Subject)对象的创建不是自己去创建,而是维托SecurityManage去创建的,我们看到传递的参数是SubjectContext,也就是使用上下文去创建Subject,因为Subject需要的信息都保存在这个Map中。

接下来我们就看看SecurityManage是怎样根据SubjectContext创建Subject; SecurityManage有三个重要的接口:
在这里插入图片描述
现在我们就是讲解其中之一的一个接口,即创建Subject,我们再来看看具体创建的整个过程,到目前为止,已经为创建Subject准备了三个内部聚合属性了分别是SecurityManage,request,response.
在这里插入图片描述
接下来,我们看到resolveSession(context)方法的调用,这个方法的作用就是把Session放入SubjectContext中,那么是怎么找到当前的用户对应的Session呢?有两种种方式:cookie和路径携带参数一个叫做JSSIONID的参数,这些参数都是在request对象中可以获取到的,这个参数值就是一个SessionId, 保存session的是个Map,通过SessionId就可以找到Session了。

重点需要说明一下Session,Session里面保存了一些特殊的属性值,我们先来看看Session结构:

在这里插入图片描述

在Session类结构中,有SessionId,Date startTimestamp;(session的创建时间),Date stopTimestamp;(session的到期时间,这个每次请求都会校验,如果Session过期会抛出异常,导致验证失败),String host(Session的创建主机),Map<Object, Object> attributes(这个Map里面保存了两个比较重要的Key,一个用来标记这个session是否做过验证<登录>,一个用来保存当前Session的授权信息<权限>),这两个Key分别是SubjectContext类里面的常量值,如下:
在这里插入图片描述

第一个是代表权限信息的Key,第二个表示是否为登录状态的Session的Key

到目前为止,SubjectContext中已经包含了(request,response,securityManage,Session)

接下来就是使用SubjectContext去创建Subject对象的时候了,我们来看看源码:
在这里插入图片描述
在方法中,会依次将SubjectContext中的值去解析出来,来满足Subject的构建方法,我们看到Subject的构造方法就是我们所说的那几个必要的参数:

1.SecurityManager securityManager = wsc.resolveSecurityManager()获取到SecurityManage对象,这个在Subject上下文早就存在了的
2.wsc.resolveSession(),这个也是一样,已经保存到了上下文中
3.PrincipalCollection principals = wsc.resolvePrincipals();这个是获取到当前Subject的权限信息的,但是在 SubjectContext中是没有直接保存的,但是还记得Session结构吗?我们已经有了Session,那么这个权限信息就可以在Map表中可以找到了
4.boolean authenticated = wsc.resolveAuthenticated();这个是判断是否做过登录,和上面一样,这个也是可以在Session中找到的。
5.String host = wsc.resolveHost();这个创建Session的主机ip也是可以在Session中找到的。

总结:Subject在shiro中是非常重要的,我们只有了解了Subject中含有哪些信息,我们在后面才能用好Subject相关的api使用过滤器去做些检查,从而达到访问控制的目的;在后面过滤器的讲解中,你们就会发现Subject的重要性,你才能更好的去理解Filter.

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值