5

目前我在我的项目中使用 Struts 2.3.12 并且一切正常。现在我需要将 Struts 版本升级到 2.3.20 以解决一些安全问题。

我在我的项目中将 Struts 和所需的 Struts 插件版本更改为 2.3.20pom.xml并构建了项目战争。现在,我正在尝试访问我的应用程序主页 URL,然后出现以下异常:

没有为与上下文路径关联的命名空间[/web/public]和操作名称映射的操作。- [未知位置][reset-password!reset][/ims]

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.xmlstruts.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
    //-------------------------------------------------------------------------

}
4

3 回答 3

1

一段时间以来一直在努力从 struts 2.3.16 升级到 2.3.20。不确定我们是否面临同样的问题,但是,我仍然在分享对我有用的解决方案。

REST 插件操作,应该使用约定按后缀索引:例如 struts.convention.action.suffix = Controller

升级所有 struts2-* jar 文件和 xwork-core.jar 后根本不工作

日志中没有打印任何内容。

最后,看到这篇文章: http : //comments.gmane.org/gmane.comp.jakarta.struts.user/186383 “我今天早上只更新了 struts2 和 xwork jar 文件后遇到了同样的问题。我更新了asm、asm-commons、asm-tree 和 commons-lang3 jar 文件复制到 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)。

希望它对您的项目也有帮助。

干杯

于 2015-03-23T12:13:20.120 回答
1

最后我找到了罪魁祸首,这是由于我的应用程序 lib forder 中包含两次版本(3.1 和 5.1)的 asm jar 冲突。升级到 struts 2.3.20 后,它正在下载 asm 5.1,并且从父应用程序 pom 中包含 asm 3.1。

此外,您还必须通过在 struts.xml 中添加以下常量来显式启用 DMI。

<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
于 2015-03-23T17:11:23.717 回答
0

由于版本发生了变化,Struts 的默认ActionMapper实现发生了显着变化。在此期间应用了许多安全修复程序。

您可以查看安全公告

问题是您将DMI与 URL 映射一起使用。DMI 默认关闭。DMI 功能在当前版本的 Struts 中可能不起作用,您应该更改操作的映射。

但在升级到 2.3.20 之前,您可以尝试升级到 2.3.16.3。

要打开 DMI,请尝试使用常量启用它:

<constant name="struts.enable.DynamicMethodInvocation" value="true"/> 
于 2015-02-25T19:55:30.867 回答