在创建WebEnvironment是也会首先查找servletcontext中是否自定义配置,默认使用IniWebEnvironment,及使用ini配置文件初始化securitymanager 。然后初始化默认的内置过滤器 。
public void init() {Ini ini = getIni();......setIni(ini);configure();}protected void configure() {this.objects.clear();WebSecurityManager securityManager = createWebSecurityManager();//创建默认wsmsetWebSecurityManager(securityManager);FilterChainResolver resolver = createFilterChainResolver();//初始化默认过滤器if (resolver != null) {setFilterChainResolver(resolver);}}最后WebEnvironment的初始化结束调用servletContext.setAttribute(ENVIRONMENT_ATTRIBUTE_KEY, environment)设置到ApplicationContext的attributes属性中,最后在ShiroFilter初始化时就会获取该对象中的WebEnvironment和FilterChainResolver 。
ShiroFilter过滤器上面分析了ShiroFilter的初始化的过程,下面就来看看在我们shiro框架下的web应用是怎么实现安全访问控制的 。
首先从OncePerRequestFilter#doFilter方法入手,他是Filter接口中定义的方法 。在tomcat处理完请求的封装时在就会依次调用所有注册的filter的doFilter方法 。
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();if ( request.getAttribute(alreadyFilteredAttributeName) != null ) {filterChain.doFilter(request, response);//防止同一个过滤器调用两次} else //noinspection deprecationif ( !isEnabled(request, response) || shouldNotFilter(request) ) {filterChain.doFilter(request, response);} else {request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);try {doFilterInternal(request, response, filterChain);} finally {request.removeAttribute(alreadyFilteredAttributeName);}}}然后,回调用父类的AbstractShiroFilter#doFilterInternal方法 。
protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain)throws ServletException, IOException {Throwable t = null;try {final ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain);final ServletResponse response = prepareServletResponse(request, servletResponse, chain);final Subject subject = createSubject(request, response);//noinspection uncheckedsubject.execute(new Callable() {public Object call() throws Exception {updateSessionLastAccessTime(request, response);executeChain(request, response, chain);return null;}});} catch (ExecutionException ex) {t = ex.getCause();} catch (Throwable throwable) {t = throwable;}...}在这个方法里面首先对tomcat中的request和response对象重写进行了封装,然后主要代码如下:
final Subject subject = createSubject(request, response);//由securitymanager创建subject.execute(new Callable() {public Object call() throws Exception {updateSessionLastAccessTime(request, response);executeChain(request, response, chain);//匹配请求URL执行内置过滤器return null;}});首先来看创建subject的过程 。
由于这是web环境,所有在shiro-web里面重写了WebSubject继承subject,以及其内部的builder静态内部类 。

文章插图
image
在创建过程中先初始化了WebSubject.Builder类,然后调用Builder.buildSubject,最后调用了SecurityManager#createSubject,其中 的subjectContext是在Builder初始化时创建的DefaultSubjectContext类,这个类负责处理本次会话的上下文对象,它的本质是一个Hashmap 。

文章插图
image
在初始化结束时默认存在如下对象:

文章插图
image
在DefaultSecurityManager#createSubject(SubjectContext)中首先克隆了一个context对象,然后依次检查其中的securitymanger,session,PrincipalCollection对象,如果不存在则创建并添加,最后再以这个context创建subject对象 。
public Subject createSubject(SubjectContext subjectContext) {SubjectContext context = copy(subjectContext);context = ensureSecurityManager(context);context = resolveSession(context);context = resolvePrincipals(context);Subject subject = doCreateSubject(context);save(subject);return subject;}其中shiro550漏洞就是在resolvePrincipals时触发的 。我们可以简单跟进看一下 。protected SubjectContext resolvePrincipals(SubjectContext context) {PrincipalCollection principals = context.resolvePrincipals();if (CollectionUtils.isEmpty(principals)) {principals = getRememberedIdentity(context);if (!CollectionUtils.isEmpty(principals)) {context.setPrincipals(principals);} else {}}return context;}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- “鲶鱼须”取代“高马尾”,中学女生发型大变样,越来越难理解了
- 安娜李的性解放,一部深入探讨自我价值和性观念的电影
- 解读机关公务员视同缴费年限规定,你真理解了吗?
- 手机丢了怎么能找回来oq
- 胡总发声,“牵手门”事件大结局,网友称:无法理解胡夫人的大度
- |张雪峰回应文科歧视,其实是家长们理解错了,忠言逆耳利于行
- 麦家琪|麦家琪儿子怒斥母亲当年行径,艳星总是被人不理解
- 现货黄金哪里可以开户卖
- 孙俪|“蔡公馆”蔡康永,怎能理解孙俪,4次家庭危机,均不是无常?
- |不带钩调漂的好处,如果是初学者,能对调漂有更深的理解
