0x00 概述
Struts2是以MVC架构为基础的WEB框架,通过WEB Filter的方式内嵌在WEB服务器中进行使用。
0x01 搭建
- 搭建一个WEB项目
- 通过Maven引入Struts2的依赖
<dependencies> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.0.5</version> </dependency> </dependencies>
- 添加Tomcat的启动环境,配置部署的WAR包,并将Struts的依赖引入到WAR中
- 安装Struts2的IDEA插件(方便后续配置高亮等,直接在Plugins搜struts2即可),在resources目录下新建一个struts.xml(如果安装了插件可以直接在新建时选择XML Configuration File -> Struts Config进行创建)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> </struts>
- 在web.xml中添加struts2的filter
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list>
上述步骤走完后,一个基本的struts2的环境就搭建完成了,后续只需要按需进行配置即可,完整的目录结构如下:
0x02 Struts2基本使用方式
2.0 action == struts2?
如果在学习Struts2相关漏洞之前有尝试过当个脚本小子用过工具去攻击存在ST2-xxx漏洞的网站,会发现实际上大部分情况下我们攻击的都是.action
后缀的文件。
那么是否.action
后缀的文件就一定会对应着使用了Struts2?答案是至少目前看来是的,还没有其他开源框架使用.action
作为自己的一个标志,除非开发者自定义了Filter。
2.1 struts.xml
struts.xml是Struts2中的一项重要配置,所有与Struts2相关的配置都在这里进行。
默认模板如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
</struts>
在大型系统下必然会存在许多的配置,并且可能每个配置关联的只是一组模块,这时候如果全部写在一个xml内未必显得太过于臃肿,此时必然会考虑通过包含的语法进行解耦,Struts2也支持这种写法,通过include引入其余xml文件。
比如我有一个user.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="wwfy" extends="struts-default">
<action name="login" class="wwfy.user.LoginAction">
<!--省略Action其他配置-->
</action>
<action name="logout" class="wwfy.user.LogoutAction">
<!--省略Action其他配置-->
</action>
</package>
</struts>
后续我只需要通过include标签将其引入到struts.xml中即可进行配置:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<include file="user.xml"/>
</struts>
constant标签用于设置一些内置常量的值,比如我们可能了解得最多的devMode。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<!--设置开发模式-->
<constant name="struts.devMode" value="true"/>
<!--设置编码形式为GB2312-->
<constant name="struts.i18n.encoding" value="GB2312"/>
<!--省略其他配置信息-->
</struts>
package标签管理某个模块下的所有action,可以将其类比为Java中的package。
属性 | 是否必需 | 描述 |
---|---|---|
name | 是 | 包名,作为其它包应用本包的标记 |
extends | 否 | 设置本包继承其它包 |
namespace | 否 | 设置包的命名空间 |
abstact | 否 | 设置为抽象包 |
extends:当前包的继承包,默认情况下需要继承struts-default这个包。
namespace:命名空间,默认情况下是""
,也可以理解为/
,此时你的默认路由在根目录下,如果设置为/user
,则当前package下的所有action都是在user目录下被匹配到。
action标签用于设置某个动作类,并且在此处会根据name自动的定义路由,也就是我们常常看到的xxx.action
。
属性名称 | 是否必须 | 功能描述 |
---|---|---|
name | 是 | 请求的Action名称 |
class | 否 | Action处理类对应具体路径 |
method | 否 | 指定Action中的方法名 |
converter | 否 | 指定Action使用的类型转换器 |
name:当前action的名称,后续设置路由也是根据name来设置的,比如这里的name是login,那么后续的路由则是login.action。
class:当前action对应的类,这个类相当于MVC中的M和C,也就是Model层和Controller层,因为具体业务处理代码是在此类中体现的,并且此类也作为一个Bean类在后续调度中被使用。
method:将调用Action类的方法名,如果不指定的话默认调用的是Action的execute方法。
result标签用于控制返回的视图。
属性名称 | 是否必须 | 功能描述 |
---|---|---|
name | 否 | 对应Action返回逻辑视图名称,默认为success |
type | 否 | 返回结果类型,默认为dispatcher |
name:设置返回值,当action class执行方法后返回对应值就会在此处根据name属性进行匹配,匹配上了就返回对应视图。
<result name="success">hello.jsp</result>
<result name="error">index.jsp</result>
Struts2中有一个拦截器的概念,类似于WEB容器中的Filter,但又有点不一样,拦截器用于在每个请求到达真正的Action之前进行一系列的预处理,并在请求结束后进行一系列的销毁动作。
Struts2内置了一系列的拦截器,并且会根据你的Action设置对应的拦截处理的操作,但是开发者依然可以自定义拦截器,通过interceptors标签即可自定义拦截器。
<interceptors>
<interceptor name="拦截器名" class="拦截器类"/>
<interceptor-stack name="拦截器栈名">
<interceptor-ref name="拦截器名">
</interceptor-stack>
</interceptors>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts
Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<package name="default" extends="struts-default">
<action name="product" class="com.javatpoint.Product">
<result name="success">welcome.jsp</result>
</action>
</package>
</struts>
上面是一个最基础的例子,其设置了一个action,名为product,后续如果要访问实际上就是通过product.action访问它。
并且设置了class为com.javapoint.Product,这表明所有product.action的请求将交由Product#execute方法来处理(因为这里没有通过method特指方法)。
最后设置了一个result标签,此时当Product#execute返回success时则会返回welcome.jsp这个视图,在welcome.jsp中可以用Struts特有的标签来获取上下文的对象信息,用于输出定制化的界面。