目前我在项目中使用Struts 2.3.12,所有的工作都很好。现在我需要将Struts版本升级到2.3.20,以解决一些安全问题。
我在我的项目pom.xml
中将Struts和所需Struts插件版本更改为2.3.20,并构建了项目war。现在,我正试图访问我的应用程序主页URL,然后得到以下异常:
命名空间
[/web/public]
和与上下文路径[/ims]
关联的操作名称[reset-password!reset]
没有映射任何操作。-【未知位置】
com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:185)
org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)
org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:37)
com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:554)
org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81)
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:125)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
org.josso.tc55.agent.SSOAgentValve.invoke(SSOAgentValve.java:472)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:875)
org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
java.lang.Thread.run(Thread.java:662)
我对正在发生的事情一无所知。
我查看了struts 2.3.20的发布说明,但没有得到任何提示。
我用的是strust2-convention-plugin
。
我正在共享我的web.xml
和struts.xml
文件。它看起来如下:
web.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="jail" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>ims</display-name>
<!-- JCaptcha servlet mapping -->
<servlet>
<servlet-name>jcaptcha</servlet-name>
<servlet-class>com.sapienza.jail.controller.jcaptcha.JailImageCaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jcaptcha</servlet-name>
<url-pattern>/web/public/jcaptcha.jpg</url-pattern>
</servlet-mapping>
<!-- Filters -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/web/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>ResponseOverrideFilter</filter-name>
<filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ResponseOverrideFilter</filter-name>
<url-pattern>/web/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/web/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/web/public/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/struts/*</url-pattern>
</filter-mapping>
<!-- JSP configuration -->
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>false</el-ignored>
<page-encoding>UTF-8</page-encoding>
<include-prelude>/jsp/common/taglibs.jspf</include-prelude>
</jsp-property-group>
</jsp-config>
<welcome-file-list>
<welcome-file>/jsp/common/home.jsp</welcome-file>
</welcome-file-list>
<!-- Spring Listener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- Skin listener -->
<listener>
<listener-class>com.sapienza.jail.listener.ResourceListener</listener-class>
</listener>
<!-- LDAP Synchronisation Listeneer -->
<listener>
<listener-class>com.sapienza.jail.listener.LdapSyncListener</listener-class>
</listener>
<!-- Tiles listener -->
<listener>
<listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
</listener>
<context-param>
<param-name>org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG</param-name>
<param-value>/WEB-INF/tiles/skins-definitions.xml,/WEB-INF/tiles/pages-definitions.xml</param-value>
</context-param>
<context-param>
<param-name>org.apache.tiles.evaluator.AttributeEvaluator</param-name>
<param-value>org.apache.tiles.evaluator.el.ELAttributeEvaluator</param-value>
</context-param>
</web-app>
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="struts-default.xml"/>
<constant name="struts.objectFactory" value="spring"/>
<constant name="struts.devMode" value="true"/>
<constant name="struts.convention.default.parent.package" value="base-configuration"/>
<constant name="struts.convention.classes.reload" value="true"/>
<constant name="struts.enableJSONValidation" value="true"/>
<!-- struts configuration common for the whole application -->
<include file="struts-base.xml"/>
</struts>
struts-base.xml
:
<struts>
<!-- This package is abstract. It is not mean to declare any actions, only
common components such as interceptors, global results ... -->
<package name="base-configuration" abstract="true" extends="tiles-default">
<result-types>
<result-type name="jasper" class="org.apache.struts2.views.jasperreports.JasperReportsResult"/>
<result-type name="json" class="org.apache.struts2.json.JSONResult"/>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult"/>
</result-types>
<!-- create a custom paramsPrepareParamsStack using our log4j interceptor -->
<interceptors>
<!-- declaration of the custom interceptor using log4j to log exceptions. -->
<interceptor name="log4jExceptionMappingInterceptor" class="log4jExceptionMappingInterceptor" />
<!-- declaration of the custom security interceptor -->
<interceptor name="securityInterceptor" class="securityInterceptor" />
<!-- declaration of the custom SearchBean interceptor -->
<interceptor name="searchBeanInterceptor" class="searchBeanInterceptor" />
<!-- declaration of the custom WhiteSpaceTrim interceptor -->
<interceptor name="whiteSpaceTrimmerInterceptor" class="whiteSpaceTrimmerInterceptor" />
<!-- Struts2 JSON Validation -->
<interceptor name="jsonValidation" class="org.apache.struts2.json.JSONValidationInterceptor" />
<interceptor-stack name="imsDefaultStack">
<!-- insert log4j interceptor inserted in the custom stack -->
<interceptor-ref name="log4jExceptionMappingInterceptor" />
<!-- insert the custom security interceptor -->
<interceptor-ref name="securityInterceptor" />
<interceptor-ref name="alias" />
<interceptor-ref name="params" />
<interceptor-ref name="servletConfig" />
<interceptor-ref name="prepare" />
<interceptor-ref name="i18n" />
<interceptor-ref name="chain" />
<interceptor-ref name="checkbox" />
<interceptor-ref name="staticParams" />
<interceptor-ref name="params" />
<!-- excludes base CRUD methods from the validation process -->
<!-- validation interceptor triggers the xml validation -->
<interceptor-ref name="validation">
<param name="validateAnnotatedMethodOnly">true</param>
<param name="excludeMethods">input,back,cancel,list,view,initCreate,initUpdate,delete</param>
</interceptor-ref>
<!-- ajax validation interceptor -->
<interceptor-ref name="jsonValidation">
<param name="excludeMethods">input</param>
</interceptor-ref>
<!-- workflow interceptor triggers programmatic validation (calls validate()) -->
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,list,view,initCreate,initUpdate,delete</param>
</interceptor-ref>
</interceptor-stack>
<!-- this new custom stack will be used for public URL -->
<interceptor-stack name="imsNoSecurityStack">
<!-- insert log4j interceptor inserted in the custom stack -->
<interceptor-ref name="log4jExceptionMappingInterceptor" />
<interceptor-ref name="alias" />
<interceptor-ref name="params" />
<interceptor-ref name="servletConfig" />
<interceptor-ref name="prepare" />
<interceptor-ref name="i18n" />
<interceptor-ref name="chain" />
<interceptor-ref name="checkbox" />
<interceptor-ref name="staticParams" />
<interceptor-ref name="params" />
<!-- excludes base CRUD methods from the validation process -->
<!-- validation interceptor triggers the xml validation -->
<interceptor-ref name="validation">
<param name="validateAnnotatedMethodOnly">true</param>
<param name="excludeMethods">input,back,cancel,list,view,initCreate,initUpdate,delete</param>
</interceptor-ref>
<!-- ajax validation interceptor -->
<interceptor-ref name="jsonValidation">
<param name="excludeMethods">input</param>
</interceptor-ref>
<!-- workflow interceptor triggers programmatic validation (calls validate()) -->
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,list,view,initCreate,initUpdate,delete</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- the new custom stack will be the default one used in the sub packages. -->
<default-interceptor-ref name="imsDefaultStack" />
<!-- exception handling -->
<global-results>
<result name="error">/jsp/common/error.jsp</result>
<result name="securityError">/jsp/common/access-denied.jsp</result>
<result name="ldapError">/jsp/common/ldap-connection-error.jsp</result>
</global-results>
<!-- any unhandled exceptions will return the error page displaying the
message of the exception. -->
<global-exception-mappings>
<exception-mapping result="error" exception="java.lang.Exception" />
<exception-mapping result="securityError" exception="com.sapienza.jail.exception.NoApplicationAccess" />
<exception-mapping result="ldapError" exception="com.sapienza.jail.exception.LDAPConnectionException" />
</global-exception-mappings>
</package>
</struts>
我在课堂上使用基于注释的动作映射,如下
@Results({
@Result(name="index", type="tiles", location="testPage"),
@Result(name = "redirect", location = "user/search-user!view", type = "redirectAction")
})
@Namespace("/web/public")
@Action
public class HomeAction extends BaseAction {
private static final Logger logger = Logger.getLogger(HomeAction.class);
private static final String SESSIONBASKET = "userSessionBasket";
//-------------------------------------------------------------------------
// Dependencies injected by spring via setters
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
// Constructor and methods
//-------------------------------------------------------------------------
public HomeAction() {
}
@Override
public String execute() {
if (isInHttpSession(SESSIONBASKET)){
getSession().removeAttribute(SESSIONBASKET);
}
return result(REDIRECT_RESULT);
}
//-------------------------------------------------------------------------
// Getters and Setters
//-------------------------------------------------------------------------
}
从struts 2.3.16升级到2.3.20已经有一段时间了。不确定我们是否面临同样的问题,但是,我仍然在分享对我有效的解决方案
REST插件操作,应该使用约定通过后缀进行索引:例如。struts.convention.action.suffix=控制器
在升级了所有的struts2-*jar文件和xwork-core.jar 后根本不工作
日志中没有打印任何内容。
最后,我看到了这篇帖子:http://comments.gmane.org/gmane.comp.jakarta.struts.user/186383"今天早上,我只更新了支柱2和xwork jar文件。我将asm、asm-commons、asm-tree和commons-lang3jar文件更新为在struts-2.3.20-lib.zip文件中找到的,问题就消失了。"
在升级asm-*.jar之后,问题也消失了
我唯一不能理解的是,2.3.20版本将一些jar文件降级,如commons validator到1.3.1(从1.4.0降级)和common collections到1.3.1(由3.2.1降级)
希望它也能帮助你的项目。
干杯
最后我找到了罪魁祸首,这是由于冲突的asm-jar,它在我的应用程序lib-foder中包含了两次版本(3.1和5.1)。在升级到struts 2.3.20之后,它下载了asm 5.1,并且从父应用程序pom中包含了asm 3.1。
此外,您还必须通过在struts.xml.中添加以下常量来显式启用DMI
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
由于版本发生了更改,Struts默认的ActionMapper
实现发生了显著变化。在此期间应用了许多安全修复程序。
你可以查看安全公告。
问题是您将DMI与URL映射一起使用。DMI在默认情况下处于关闭状态。DMI特性在Struts的当前版本中可能不起作用,您应该更改操作的映射。
但在升级到2.3.20之前,您可以尝试升级到2.3.16.3。
要打开DMI,请尝试使用常量启用它:
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>