首先spring+Thymeleaf必过的点
org.springframework.web.servlet.DispatcherServlet#doDispatch

那么先跟入handle()方法

然后跟进handleInternal方法

可以看到mav的获取方法,继续跟进invokeHandlerMethod

继续跟进invokeAndHandle

这里判断returnvalue是否有值,决定了2种类型的payload。returnValue的获取会invoke此Request对应的函数获取返回值,例如下面这个例子访问/path时,获取return的值为user/{lang}/welcome作为ModelAndView的view值。
@GetMapping("/path")
public String path(@RequestParam String lang) {
return "user/" + lang + "/welcome";
}
但如果例子是下面这样的呢?此时ModelAndView的view值为null。
@DeleteMapping(value = "/{username}")
public void deleteUser(@PathVariable(name = "username") String username) {}
}
接着往下来到第二个过程,跟进applyDefaultViewName()。

跟进applyDefaultViewName方法

若ModelAndView对象中的view不为空,则啥也不做,否则会获取DefaultView作为View。来看看defaultview是如何获取的。跟进getDefaultViewName(),(注意:这里我调试没有走到这里,断点走不过去)
继续跟进viewNameTranslator.getViewName()。

跟进getViewName

在该方法中首先获取uri的path值,然后进入transformPath()方法,最后和prefix以及suffix进行拼接,即为ViewName。跟进transformPath()。继续跟进transformPath

在这里会去掉前后的/,它会将.及之后的内容当作扩展名,会截掉.以及之后的内容。因此,这种情况下需要在payload后增加一个.以保证payload内容完整。
解析表达式
获得view之后,接下来跟进processDispatchResult

我们都知道render()是用来模板渲染的,跟进render()

首先获取viewName,然后调用resolveViewName()函数,可以看到此时mv取值为
ModelAndView [view="monitor/cache/cache::${T (java.lang.Runtime).getRuntime().exec("calc.exe")}";
model={cacheNames=[Ljava.lang.String;@7150b74}]

跳入resolveViewName

这里选择bestview,

这里往往返回ThymeleafView,保持了和view一样的值,接着往下
调用了view.render(),即ThymeleafView…render(),跟进

继续跟进


可以看到这里判断viewTemplateName中是否包含::符号,如果包含就StandardExpressionParser.parseExpression来解析,格式为
"~{" + viewTemplateName + "}"
跟进parseExpression

可以看到这是第一次解析,然后return的时候还有第二次解析(Expression)parseExpression(context, input, true);
继续跟进parseExpression

这里首先调用preprocess对__${}__里的内容进行预处理,结果存入 preprocessedInput,然后调用Expression.parse()进行第二次解析表达式。
在第一次处理时,只要__${}__里面的语法正确,是一定会被执行的。执行完的第二次表达式解析是否正确就不一定了。如果第二次执行失败,则会显示原来的viewTemplateName值,而没有回显,但事实上已经执行了恶意语句。影响第二次执行失败与否与~{}里的语法格式有关。

当~{}中出现::,其后面需要有值
最后在如下步骤弹出计算器












![河湖长制综合管理信息平台建设项目总体设计方案[507页Word]](https://img-blog.csdnimg.cn/img_convert/c641e5913afe69b78c320bed32186689.jpeg)







