tomcat解析(十八)对客户请求的处理2

当我们在web.xml里配置了对系统资源访问的保护后,每次客户端发起访问都需要经过AuthenticatorBase及其子类的校验,大多共用的处理放在AuthenticatorBase中,其它独立于各种校验方式的处理放于其子类中,让我们先看一下AuthenticatorBase中做了哪些事情
<1>校验当前用户是否已经经过了校验,并且我们已将其校验通过的通行证明放到了该用户的Session中.
 

<2>这个校验主要是对于auth-method为Form类型的方式,需要校验请求是否来自登录界面,对于从login-page界面上来到的请求进行核对其权限
 

如果通过权限校验,表示可以访问该资源,则继续做下面的校验,否则直接返回(因为子类的校验里已处理的重定向问题).
<3>查看当前请求是否对应了<security-constraint>中设置的资源,如果没有,则直接调用pipeline下一个处理类(StandardContext的basic pipeline:StandardContextValve)进行处理并直接返回不进行其它的校验.
 

<4>核对是否需要进行角色权限校验,调用子类authenticate方法进行校验,当校验时发现所访问的资源有权限控制,但当前用户没有授权时是重定向到登录界面<login-page>,但当校验结果为失败或错误时,直接返回(原因同第2点)
 

本文的重点在于让大家了解tomcat是如何做资源权限的控制的,下面以FormAuthenticator.authenticate为例.该方法中有很多内容是对用户是否已经授过权,是否有相应的SSO缓存或其它授权缓存之类的信息进行校验,对于这种校验,如果一开始看实在很难开明白是否能获取到相应的内容,但当我们以一个新用户的方式来进行处理(即是说假定这些校验全都不通过),再看其后面相应的处理,就会发现与前面的校验互相对应,我们在讲这一部分内容的时候也会以这种方式来讲解:
<1>我们假定没有SSO,也还没有授权缓存信息,只按完全的新用户来处理,则程序将直接来到这一部分处理
 

1.请求的地址不是由/j_security_check结尾
2.先获得session,此时如果没有已创建的Session对象则新创建一个
3.保存现在的请求地址,将实例化一个SavedRequest对象,并调用下列Session方法:session.setNote(Constants.FORM_REQUEST_NOTE, SavedRequest);
4.重定向到登录界面,保存现有请求地址的目的是为了在登录之后即可定向到先前请求的地址,实现更好的人性化
5.方法返回false,在AuthenticatorBase.invoke方法中,在执行完子类的authenticate方法并返回false时,invoke方法直接返回,不再调用getNext().invoke(request, response)继续request的处理.

在登录界面输入用户名密码后系统依然是一样的处理方式,到AuthenticatorBase.invoke,此时将走如下判断
 

依然看子类FormAuthenticator.authenticate中会进行如下操作
    

1.从request分别取出j_username和j_password
2.调用realm.authenticate进行校验,若是校验不通过,直接重定向到错误界面,返回false,则父类后续不会继续处理,用户名密码校验通过,继续进行下面的操作
3.设置session相关属性,包括Constants.FORM_PRINCIPAL_NOTE,Constants.SESS_USERNAME_NOTE及Constants.SESS_PASSWORD_NOTE
4.取出已保存的客户请求地址,重定向到该地址,返回false,父类的invoke方法不会再调用其后续的处理类进行操作
虽已经通过了用户名密码校验,并且将请求重定向到原先的请求,但当原先请求进来时,依然对其进行了客户校验的处理,不过这时就简单得多,子类FormAuthenticator.authenticate,此时将走下面的一段逻辑
 

此时判断为当前的请求与之前保存的请求一致,于是调用register注册已得到的UserPricipal实例,大致内容是将该实例设置到request,session等对象中,并产生Cookie或SSO等内容.有一点需要注意session.setPrincipal(principal),这里将该实例放入Session级别是为了后续该用户继续对其它受保护资源进行访问的时间获得其已授权的证书说明;在注册完当前用户的UserPricipal后,将调用restoreRequest方法将先前保存的请求的各项属性迁移到当前的请求中,包括Cookies,Method,Head,Locales及QueryString等内容,是为了让当前请求完全恢复为已保存请求的内容,结束后返回到父类AuthenticatorBase.invoke方法,而该方法则将调用下一处理类(Wrapper及Servlet)对此请求进行处理并返回处理结果;
我们可以再看一下当用户再访问其它受限资源的时候会做什么,依然先到父类AuthenticatorBase.invoke方法,此时先会执行下面这一段,注意session.getPrincipal()是如何得来的(本文有)
  

  将存储于Session中的UserPricipal再放到当前的request里(大家想也知道是用来干嘛的啦),再经过一段其它无关痛痒的判断,最后还是到子类的authenticate方法,在方法开始地方有如下内容:
  

  这里又从当前request取出该UserPricipal,不为空时(先不说sso)直接返回true,又回到父类AuthenticatorBase.invoke,此时将调用getNext().invoke(request, response);
  在这里将调用StandardContextValve的相应方法(原因可看StandardContext的构造方法及ContextConfig.start-->authenticatorConfig的相应内容)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值