Struts2.0一下,升级到Struts2.5的问题

本文详细记录了一个开发者在将老项目从Struts2的旧版本升级到2.5.30过程中遇到的挑战,包括MethodNotAllowed错误和codebehind插件替换为convention插件的问题。在尝试了常规配置方法无效后,开发者深入研究源码,实现了自定义的ActionConfigBuilder以解决方法调用限制,并处理了XML配置的全局结果与convention不互通的问题。最终,通过自定义扩展成功解决了所有问题。

朋友求助,老项目客户要求升级到Struts2.5.30,规避必要漏洞和风险。搞了一两周没进展。

1、Method XX from action XX is not allowed!

网上方法基本是在XML中进行配置,算基本配置吧,包括

1)package标签中增加方法通配符

<global-allowed-methods>regex:.*</global-allowed-methods>

2)package标签增加 strict-method-invocation="false" 属性配置

<package name="security" namespace="/xframe/security" extends="XXXDefault" 
    strict-method-invocation="false">

这个属性Struts2.5默认是SMI为true,且不能全局设置,只能一个个Package进行设置,不申明的都不允许访问。然后就是配置在struts.xml中的action可以用了,但自动扫描的包都不行。

网上能搜到的基本就是这个配置,但怎么都不行。

在仔细研究。

2、codebehind插件,替换为struts2.3引入替换的新插件convention

接上条,仔细研究后,发现老项目用的codebehind插件,简化配置。该插件会自动扫描制定的源码包,把扫描出来的action和响应方法都暴露给外面允许访问。

这恰恰是Struts2.5安全性能提升到的一个点。于是换convertion。

convertion的主要配置如下:

<!-- 限制方法调用之方法前缀 -->
<constant name="struts.strictMethodInvocation.methodRegex" value="([A-Za-z]*)"/>
<!-- 进行扫描的根包,该包会被扫描成action -->
<constant name="struts.convention.action.packages" value="com.xx" />
<!-- 指定的包会被进行扫描 -->
<constant name="struts.convention.package.locators" value="action,actions,web" />
<!-- 返回页面地址 -->
<constant name="struts.convention.result.path" value="/pages/" />
<!-- 用于进行action查找的后缀 -->
<constant name="struts.convention.action.suffix" value="Action" />

然后,发现依旧是not allowed!

3、自定义convention扩展

卡了好长时间,最后下载了Struts2.5的全套源码,通过eclipse设置源码后开始调试。发现在请求的时候,convention自动扫描到的Action,在请求的时候,生成的ActionConfig中的actionMethod压根就没有Package的global-allowed-method允许的通配符。然后通过XML配置进来的action确有通配符。

convertion和XML不通!!!

有卡壳,继续研究,尤其是官方的文档和WIKI

Convention plugin (apache.org)https://struts.apache.org/plugins/convention/Convention Plugin - Apache Struts 2 Wiki - Apache Software Foundationhttps://cwiki.apache.org/confluence/display/WW/Convention+Plugin发现没有任何这方面的说明。没有!

然后是发现可以扩展convention,官方文档中的overwriting部分。

Convention plugin (apache.org)https://struts.apache.org/plugins/convention/#overwriting-plugin-classes最后的扩展如下:

1)配置,在Struts.xml中配置自己的

<bean type="org.apache.struts2.convention.ActionConfigBuilder" 
   name="convention1" class="com.xxx.security.PackageBasedActionConfigBuilderCustom"></bean>
<constant name="struts.convention.actionConfigBuilder" value="convention1"/>

发现convention的PackageBasedActionConfigBuilder本身代码也很多,1141行。就没有按说明实现interface,而是直接继承了PackageBasedActionConfigBuilder,然后多关键方法做覆盖。

2)PackageBasedActionConfigBuilderCustom类

2.1)构造方法

@Inject
public PackageBasedActionConfigBuilderCustom(Configuration configuration, Container container, ObjectFactory objectFactory,
  @Inject(ConventionConstants.CONVENTION_REDIRECT_TO_SLASH) String redirectToSlash,
  @Inject(ConventionConstants.CONVENTION_DEFAULT_PARENT_PACKAGE) String defaultParentPackage) {
   super(configuration, container, objectFactory, redirectToSlash,defaultParentPackage);
    // Validate that the parameters are okay
   this.configuration = configuration;
   this.actionNameBuilder = container.getInstance(ActionNameBuilder.class, container.getInstance(String.class, ConventionConstants.CONVENTION_ACTION_NAME_BUILDER));
   this.resultMapBuilder = container.getInstance(ResultMapBuilder.class, container.getInstance(String.class, ConventionConstants.CONVENTION_RESULT_MAP_BUILDER));
// this.interceptorMapBuilder = container.getInstance(InterceptorMapBuilder.class, container.getInstance(String.class, ConventionConstants.CONVENTION_INTERCEPTOR_MAP_BUILDER));
   this.objectFactory = objectFactory;

//        this.redirectToSlash = Boolean.parseBoolean(redirectToSlash);

   if (LOG.isTraceEnabled()) {
      LOG.trace("Setting action default parent package to [{}]", defaultParentPackage);
    }

//        this.defaultParentPackage = defaultParentPackage;
}

先调用父类的,其他变量是为了方便后面引用的。

2.2)createActionConfig

/**
 * Creates a single ActionConfig object.
 *
 * @param pkgCfg       The package the action configuration instance will belong to.
 * @param actionClass  The action class.
 * @param actionName   The name of the action.
 * @param actionMethod The method that the annotation was on (if the annotation is not null) or
 *                     the default method (execute).
 * @param annotation   The ActionName annotation that might override the action name and possibly
 */

protected void createActionConfig(PackageConfig.Builder pkgCfg, Class<?> actionClass, String actionName,
                                  String actionMethod, Action annotation, Set<String> allowedMethods) {
	
	Set<String> ss = new HashSet<>();
	ss.add("regex:.*");
	pkgCfg.addGlobalAllowedMethods(ss);

	super.createActionConfig(pkgCfg, actionClass, actionName, actionMethod, annotation, allowedMethods);

	//判断nameSpace空间是否严格限制方法调用,默认是不允许的。
	pkgCfg.strictMethodInvocation(false);
	
	packageNum++;
	
	LOG.debug(packageNum + "\t" + pkgCfg.getNamespace() + "\t" + actionName + "\t" + actionMethod + "\t" + actionClass.getName());
	
}

本方法一是给自动构建的package增加GlobalAllowedMethods通配符,二是关闭方法调用严格限制。

如此,Not Allowed终于解决了。

2.3)Could not find action or result

之后还发现一个问题,找不到XML中配置的全局Result

<global-results>
	<result name="error">/pages/xframe/global/Error.jsp</result>
	<result name="login-input" type="redirectAction">
		<param name="actionName">Login</param>
		<param name="method">input</param>
		<param name="namespace">/</param>
	</result>
</global-results>
Could not find action or result:/xxx/.action

Could not find action or result

全局设定,也是为了简化处理的。但在XML中配置的内容,和convention中还是不互通。

重新修改了上述方法如下。

protected void createActionConfig(PackageConfig.Builder pkgCfg, Class<?> actionClass, String actionName,
                                  String actionMethod, Action annotation, Set<String> allowedMethods) {

	//获取XML中的defaultParentPackage对应的GlobalResult
	for(String cfgName :this.configuration.getPackageConfigNames()){
		PackageConfig cfg  = this.configuration.getPackageConfig(cfgName);//XML中的defaultParentPackage
		Map<String, ResultConfig>  map = cfg.getGlobalResultConfigs();
    	if(map.size() > 0){
    		pkgCfg.addGlobalResultConfigs(map);
    	}
	}
	
	Set<String> ss = new HashSet<>();
	ss.add("regex:.*");
	pkgCfg.addGlobalAllowedMethods(ss);

	super.createActionConfig(pkgCfg, actionClass, actionName, actionMethod, annotation, allowedMethods);

	//判断nameSpace空间是否严格限制方法调用,默认是不允许的。
	pkgCfg.strictMethodInvocation(false);
	
	packageNum++;
	
	LOG.debug(packageNum + "\t" + pkgCfg.getNamespace() + "\t" + actionName + "\t" + actionMethod + "\t" + actionClass.getName());

}

至此,问题解决。

其他诸如Convention扫描出来的Package的Namespace不规范等,单独写一个方法重新生成Namespace和ActionName即可。

数据集介绍:液滴检测YOLO目标检测数据集一、基础信息数据集名称:液滴检测YOLO目标检测数据集图片数量:- 训练集:4,616张图片- 验证集:379张图片分类类别:- droplet:液滴检测核心类别,适用于单类别目标检测任务标注格式:- YOLO格式标注,包含边界框和类别标签,可直接适配主流深度学习框架(如YOLOv5/YOLOv8等)数据特性:- 覆盖多种液滴形态及分布场景- 标注文件与图片一一对应,支持快速模型训练二、适用场景工业自动化检测:- 用于喷墨打印、涂装工艺等场景中的液滴分布质量监控- 液体设备(如喷雾器、滴管)的效能评估与优化农业科技应用:- 农药喷洒均匀度检测- 灌溉系统水滴覆盖范围分析实验室研究:- 流体力学实验中液滴运动轨迹追踪- 化学/生物实验中的微液滴反应监测环境监测:- 降雨量模拟实验中的雨滴检测- 雾化设备的环境湿度调控三、数据集优势高纯度标注质量:- 专注单类别液滴检测,标注一致性极强- 所有标注经过双重质检,边界框定位精准场景覆盖全面:- 包含静态液滴、动态飞溅、密集分布等多种状态- 涵盖不同光照条件与背景复杂度的检测场景工程适配性强:- 原生YOLO格式标注,无需格式转换即可投入训练- 兼容工业级检测模型的快速部署需求科研价值突出:- 为流体动力学、精准农业等领域的量化研究提供数据支撑- 支持从基础检测到运动轨迹预测的多阶段研究扩展
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值