| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"/> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"/> |
| <meta name="Date-Revision-yyyymmdd" content="20140918"/> |
| <meta http-equiv="Content-Language" content="en"/> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
| |
| <title>Parameters Interceptor</title> |
| |
| <link href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,400italic,600italic,700italic" rel="stylesheet" type="text/css"> |
| <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet"> |
| <link href="/css/main.css" rel="stylesheet"> |
| <link href="/css/custom.css" rel="stylesheet"> |
| <link href="/css/syntax.css" rel="stylesheet"> |
| |
| <script src="//code.jquery.com/jquery-1.11.0.min.js"></script> |
| <script type="text/javascript" src="/bootstrap/js/bootstrap.js"></script> |
| <script type="text/javascript" src="/js/community.js"></script> |
| |
| <!-- Matomo --> |
| <script> |
| var _paq = window._paq = window._paq || []; |
| /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ |
| /* We explicitly disable cookie tracking to avoid privacy issues */ |
| _paq.push(['disableCookies']); |
| _paq.push(['trackPageView']); |
| _paq.push(['enableLinkTracking']); |
| (function() { |
| var u="//analytics.apache.org/"; |
| _paq.push(['setTrackerUrl', u+'matomo.php']); |
| _paq.push(['setSiteId', '41']); |
| var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; |
| g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); |
| })(); |
| </script> |
| <!-- End Matomo Code --> |
| </head> |
| <body> |
| |
| <a href="https://github.com/apache/struts" class="github-ribbon"> |
| <img decoding="async" loading="lazy" style="position: absolute; right: 0; border: 0;" width="149" height="149" src="https://github.blog/wp-content/uploads/2008/12/forkme_right_red_aa0000.png?resize=149%2C149" class="attachment-full size-full" alt="Fork me on GitHub" data-recalc-dims="1"> |
| </a> |
| |
| <header> |
| <nav> |
| <div role="navigation" class="navbar navbar-default navbar-fixed-top"> |
| <div class="container"> |
| <div class="navbar-header"> |
| <button type="button" data-toggle="collapse" data-target="#struts-menu" class="navbar-toggle"> |
| Menu |
| <span class="sr-only">Toggle navigation</span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| </button> |
| <a href="/index.html" class="navbar-brand logo"><img src="/img/struts-logo.svg"></a> |
| </div> |
| <div id="struts-menu" class="navbar-collapse collapse"> |
| <ul class="nav navbar-nav"> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Home<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/index.html">Welcome</a></li> |
| <li><a href="/download.cgi">Download</a></li> |
| <li><a href="/releases.html">Releases</a></li> |
| <li><a href="/announce-2024.html">Announcements</a></li> |
| <li><a href="http://www.apache.org/licenses/">License</a></li> |
| <li><a href="https://www.apache.org/foundation/thanks.html">Thanks!</a></li> |
| <li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li> |
| <li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy Policy</a></li> |
| </ul> |
| </li> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Support<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/mail.html">User Mailing List</a></li> |
| <li><a href="https://issues.apache.org/jira/browse/WW">Issue Tracker</a></li> |
| <li><a href="/security.html">Reporting Security Issues</a></li> |
| <li><a href="/commercial-support.html">Commercial Support</a></li> |
| <li class="divider"></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Migration+Guide">Version Notes</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Security+Bulletins">Security Bulletins</a></li> |
| <li class="divider"></li> |
| <li><a href="/maven/project-info.html">Maven Project Info</a></li> |
| <li><a href="/maven/struts2-core/dependencies.html">Struts Core Dependencies</a></li> |
| <li><a href="/maven/struts2-plugins/modules.html">Plugin Dependencies</a></li> |
| </ul> |
| </li> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Documentation<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/birdseye.html">Birds Eye</a></li> |
| <li><a href="/primer.html">Key Technologies</a></li> |
| <li><a href="/kickstart.html">Kickstart FAQ</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Home">Wiki</a></li> |
| <li class="divider"></li> |
| <li><a href="/getting-started/">Getting Started</a></li> |
| <li><a href="/security/">Security Guide</a></li> |
| <li><a href="/core-developers/">Core Developers Guide</a></li> |
| <li><a href="/tag-developers/">Tag Developers Guide</a></li> |
| <li><a href="/maven-archetypes/">Maven Archetypes</a></li> |
| <li><a href="/plugins/">Plugins</a></li> |
| <li><a href="/maven/struts2-core/apidocs/index.html">Struts Core API</a></li> |
| <li><a href="/tag-developers/tag-reference.html">Tag reference</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/FAQs">FAQs</a></li> |
| <li><a href="http://cwiki.apache.org/S2PLUGINS/home.html">Plugin registry</a></li> |
| </ul> |
| </li> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Contributing<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/youatstruts.html">You at Struts</a></li> |
| <li><a href="/helping.html">How to Help FAQ</a></li> |
| <li><a href="/dev-mail.html">Development Lists</a></li> |
| <li class="divider"></li> |
| <li><a href="/submitting-patches.html">Submitting patches</a></li> |
| <li><a href="/builds.html">Source Code and Builds</a></li> |
| <li><a href="/coding-standards.html">Coding standards</a></li> |
| <li><a href="/contributors/">Contributors Guide</a></li> |
| <li class="divider"></li> |
| <li><a href="/release-guidelines.html">Release Guidelines</a></li> |
| <li><a href="/bylaws.html">PMC Charter</a></li> |
| <li><a href="/volunteers.html">Volunteers</a></li> |
| <li><a href="https://gitbox.apache.org/repos/asf?p=struts.git">Source Repository</a></li> |
| <li><a href="/updating-website.html">Updating the website</a></li> |
| </ul> |
| </li> |
| <li class="apache"><a href="http://www.apache.org/"><img src="/img/apache.png"></a></li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </nav> |
| </header> |
| |
| |
| <article class="container"> |
| <section class="col-md-12"> |
| <a class="edit-on-gh" href="https://github.com/apache/struts-site/edit/master/source/core-developers/parameters-interceptor.md" title="Edit this page on GitHub">Edit on GitHub</a> |
| |
| <a href="interceptors.html" title="back to Interceptors"><< back to Interceptors</a> |
| |
| <h1 class="no_toc" id="parameters-interceptor">Parameters Interceptor</h1> |
| |
| <ul id="markdown-toc"> |
| <li><a href="#parameters" id="markdown-toc-parameters">Parameters</a></li> |
| <li><a href="#excluding-parameters" id="markdown-toc-excluding-parameters">Excluding parameters</a></li> |
| <li><a href="#excluding-parameter-values" id="markdown-toc-excluding-parameter-values">Excluding parameter values</a></li> |
| <li><a href="#extending-the-interceptor" id="markdown-toc-extending-the-interceptor">Extending the Interceptor</a></li> |
| <li><a href="#warning-on-missing-parameters" id="markdown-toc-warning-on-missing-parameters">Warning on missing parameters</a> <ul> |
| <li><a href="#examples" id="markdown-toc-examples">Examples</a></li> |
| </ul> |
| </li> |
| </ul> |
| |
| <p>This interceptor sets all parameters on the value stack.</p> |
| |
| <p>This interceptor gets all parameters from <code class="language-plaintext highlighter-rouge">ActionContext#getParameters()</code> and sets them on the value stack by calling |
| <code class="language-plaintext highlighter-rouge">ValueStack#setValue(String, Object)</code>, typically resulting in the values submitted in a form request being applied |
| to an action in the value stack. Note that the parameter map must contain a <code class="language-plaintext highlighter-rouge">String</code> key and often containers a <code class="language-plaintext highlighter-rouge">String[]</code> |
| for the value.</p> |
| |
| <p>The interceptor takes one parameter named <code class="language-plaintext highlighter-rouge">ordered</code>. When set to true action properties are guaranteed to be set top-down |
| which means that top action’s properties are set first. Then it’s subcomponents properties are set. The reason for this |
| order is to enable a “factory” pattern. For example, let’s assume that one has an action that contains a property named |
| <code class="language-plaintext highlighter-rouge">modelClass</code> that allows to choose what is the underlying implementation of model. By assuring that <code class="language-plaintext highlighter-rouge">modelClass</code> |
| property is set before any model properties are set, it’s possible to choose model implementation during |
| <code class="language-plaintext highlighter-rouge">action.setModelClass()</code> call. Similarly it’s possible to use <code class="language-plaintext highlighter-rouge">action.setPrimaryKey()</code> property set call to actually |
| load the model class from persistent storage. Without any assumption on parameter order you have to use patterns |
| like <a href="prepare-interceptor">Preparable Interface</a>.</p> |
| |
| <p>Because parameter names are effectively OGNL statements, it is important that security be taken in to account. This |
| interceptor will not apply any values in the parameters map if the expression contains an assignment (=), multiple |
| expressions (,), or references any objects in the context (#). This is all done in the <code class="language-plaintext highlighter-rouge">#acceptableName(String)</code> |
| method. In addition to this method, if the action being invoked implements the <code class="language-plaintext highlighter-rouge">ParameterNameAware</code> interface, the action |
| will be consulted to determine if the parameter should be set.</p> |
| |
| <p>In addition to these restrictions, a flag (<code class="language-plaintext highlighter-rouge">ReflectionContextState#DENY_METHOD_EXECUTION</code>) is set such that no methods |
| are allowed to be invoked. That means that any expression such as <code class="language-plaintext highlighter-rouge">person.doSomething()</code> or <code class="language-plaintext highlighter-rouge">person.getName()</code> will be |
| explicitly forbidden. This is needed to make sure that your application is not exposed to attacks by malicious users.</p> |
| |
| <p>While this interceptor is being invoked, a flag (<code class="language-plaintext highlighter-rouge">ReflectionContextState#CREATE_NULL_OBJECTS</code>) is turned on to ensure |
| that any null reference is automatically created - if possible. See the type conversion documentation |
| and the <code class="language-plaintext highlighter-rouge">InstantiatingNullHandler</code> javadocs for more information.</p> |
| |
| <p>Finally, a third flag (<code class="language-plaintext highlighter-rouge">XWorkConverter#REPORT_CONVERSION_ERRORS</code>) is set that indicates any errors when converting |
| the values to their final data type (<code class="language-plaintext highlighter-rouge">String[] -> int</code>) an unrecoverable error occurred. With this flag set, the type |
| conversion errors will be reported in the action context. See the type conversion documentation and the <code class="language-plaintext highlighter-rouge">XWorkConverter</code> |
| javadocs for more information.</p> |
| |
| <p>Since Struts 6.1.0 this interceptor also implements a <code class="language-plaintext highlighter-rouge">ParameterValueAware</code> interface. This interface, in conjunction |
| with the optional <code class="language-plaintext highlighter-rouge">excludeValuePatterns</code>, can be used to validate the parameter value(s) being set by the interceptor. |
| If the value being set is excluded / not accepted the entire parameter will be dropped. This can be leveraged |
| to mitigate against forced OGNL evaluation due to unsanitized user input being echoed back as part of the action result. |
| This is not intended to replace good coding habits as described on |
| <a href="../../security/#proactively-protect-from-ognl-expression-injections-attacks-if-easily-applicable">Proactively protect from OGNL Expression Injections attacks if easily applicable</a> |
| and is available as part of a defense in depth methodology. By default excludeValuePatterns is not defined.</p> |
| |
| <p>If you are looking for detailed logging information about your parameters, turn on <code class="language-plaintext highlighter-rouge">DEBUG</code> level logging for this |
| interceptor. A detailed log of all the parameter keys and values will be reported.</p> |
| |
| <p>Since XWork 2.0.2, this interceptor extends <code class="language-plaintext highlighter-rouge">MethodFilterInterceptor</code>, therefore being able to deal with |
| excludeMethods/includeMethods parameters. See <a href="default-workflow-interceptor">Default Workflow Interceptor</a> |
| for documentation and examples on how to use this feature.</p> |
| |
| <p>For more information on ways to restrict the parameter names allowed, see the <code class="language-plaintext highlighter-rouge">ParameterNameAware</code> javadocs.</p> |
| |
| <h2 id="parameters">Parameters</h2> |
| |
| <ul> |
| <li><code class="language-plaintext highlighter-rouge">ordered</code> - set to true if you want the top-down property setter behaviour</li> |
| <li><code class="language-plaintext highlighter-rouge">acceptParamNames</code> - a comma delimited list of regular expressions to describe a allowlist of accepted parameter names. |
| Don’t change the default unless you know what you are doing in terms of security implications</li> |
| <li><code class="language-plaintext highlighter-rouge">excludeParams</code> - a comma delimited list of regular expressions to describe a denylist of not allowed parameter names</li> |
| <li><code class="language-plaintext highlighter-rouge">acceptedValuePatterns</code> - a comma delimited list of regular expressions to describe a allowlist of accepted parameter values</li> |
| <li><code class="language-plaintext highlighter-rouge">excludeValuePatterns</code> - a comma delimited list of regular expressions to describe a denylist of not allowed parameter values</li> |
| <li><code class="language-plaintext highlighter-rouge">paramNameMaxLength</code> - the maximum length of parameter names; parameters with longer names will be ignored; |
| the default is 100 characters</li> |
| </ul> |
| |
| <h2 id="excluding-parameters">Excluding parameters</h2> |
| |
| <p>This interceptor can be forced to ignore parameters, by setting its <code class="language-plaintext highlighter-rouge">excludeParams</code> attribute. This attribute accepts |
| a comma separated list of regular expressions. When any of these expressions match the name of a parameter, such parameter |
| will be ignored by the interceptor. Interceptor stacks defined by Struts already exclude some parameters:</p> |
| |
| <p><strong>Default List of Parameters Excluded</strong></p> |
| |
| <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dojo..*,^struts..*,^session..*,^request..*,^application..*,^servlet(Request|Response)..*,parameters...* |
| </code></pre></div></div> |
| |
| <p>Below is an example of adding a parameter named submit to the list of parameters that should be excluded.</p> |
| |
| <p><strong>Setup Interceptor Stack To Exclude submit Parameter</strong></p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><interceptors></span> |
| <span class="nt"><interceptor-stack</span> <span class="na">name=</span><span class="s">"appDefault"</span><span class="nt">></span> |
| <span class="nt"><interceptor-ref</span> <span class="na">name=</span><span class="s">"defaultStack"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"exception.logEnabled"</span><span class="nt">></span>true<span class="nt"></param></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"exception.logLevel"</span><span class="nt">></span>ERROR<span class="nt"></param></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"params.excludeParams"</span><span class="nt">></span>dojo..*,^struts..*,^session..*,^request..*,^application..*,^servlet(Request|Response)..*,parameters...*,submit<span class="nt"></param></span> |
| <span class="nt"></interceptor-ref></span> |
| <span class="nt"></interceptor-stack></span> |
| <span class="nt"></interceptors></span> |
| |
| <span class="nt"><default-interceptor-ref</span> <span class="na">name=</span><span class="s">"appDefault"</span> <span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <h2 id="excluding-parameter-values">Excluding parameter values</h2> |
| |
| <p>This interceptor can be forced to ignore parameters based on the value, by setting its <code class="language-plaintext highlighter-rouge">excludedValuePatterns</code> attribute. This attribute accepts |
| a comma separated list of regular expressions. When any of these expressions match the value of a parameter, such parameter will be ignored |
| by the interceptor.</p> |
| |
| <p>It’s also possible to define <code class="language-plaintext highlighter-rouge">acceptedValuePatterns</code> to accept only values that match the defined set of patterns.</p> |
| |
| <p>Below is an example of adding parameter values ${} and %{} to the list of parameter values that should be excluded |
| and only accept <strong>a-z</strong> or <strong>0-9</strong>.</p> |
| |
| <p><strong>Setup Interceptor Stack To Exclude ${ and %{ Parameter Values</strong></p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><interceptors></span> |
| <span class="nt"><interceptor-stack</span> <span class="na">name=</span><span class="s">"appDefault"</span><span class="nt">></span> |
| <span class="nt"><interceptor-ref</span> <span class="na">name=</span><span class="s">"defaultStack"</span><span class="nt">></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"exception.logEnabled"</span><span class="nt">></span>true<span class="nt"></param></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"exception.logLevel"</span><span class="nt">></span>ERROR<span class="nt"></param></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"params.excludedValuePatterns"</span><span class="nt">></span>.*\$\{.*?\}.*,.*%\{.*?\}.*<span class="nt"></param></span> |
| <span class="nt"><param</span> <span class="na">name=</span><span class="s">"params.acceptedValuePatterns"</span><span class="nt">></span>[a-zA-Z0-9]*<span class="nt"></param></span> |
| <span class="nt"></interceptor-ref></span> |
| <span class="nt"></interceptor-stack></span> |
| <span class="nt"></interceptors></span> |
| |
| <span class="nt"><default-interceptor-ref</span> <span class="na">name=</span><span class="s">"appDefault"</span> <span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <h2 id="extending-the-interceptor">Extending the Interceptor</h2> |
| |
| <p>The best way to add behavior to this interceptor is to utilize the <code class="language-plaintext highlighter-rouge">ParameterNameAware</code> and <code class="language-plaintext highlighter-rouge">ParameterValueAware</code> |
| interfaces in your actions. However, if you wish to apply a global rule that isn’t implemented in your action, then |
| you could extend this interceptor and override the <code class="language-plaintext highlighter-rouge">#acceptableName(String)</code> and/or <code class="language-plaintext highlighter-rouge">#acceptableParameterValue(String)</code> |
| method.</p> |
| |
| <blockquote> |
| <p>Using <code class="language-plaintext highlighter-rouge">ParameterNameAware</code> could be dangerous as <code class="language-plaintext highlighter-rouge">ParameterNameAware#acceptableParameterName(String)</code> takes precedence |
| over <code class="language-plaintext highlighter-rouge">ParametersInterceptor</code> which means if <code class="language-plaintext highlighter-rouge">ParametersInterceptor</code> excluded given parameter name you can accept |
| it with <code class="language-plaintext highlighter-rouge">ParameterNameAware#acceptableParameterName(String)</code>.</p> |
| </blockquote> |
| |
| <blockquote> |
| <p>The best idea is to define very tight restrictions with <code class="language-plaintext highlighter-rouge">ParametersInterceptor</code> and relax them per action |
| with <code class="language-plaintext highlighter-rouge">ParameterNameAware#acceptableParameterName(String)</code> and/or <code class="language-plaintext highlighter-rouge">ParameterValueAware#acceptableParameterValue(String)</code></p> |
| </blockquote> |
| |
| <h2 id="warning-on-missing-parameters">Warning on missing parameters</h2> |
| |
| <p>When there is no setter for given parameter name, a warning message like below will be logged in devMode:</p> |
| |
| <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SEVERE: Developer Notification (set struts.devMode to false to disable this message): |
| Unexpected Exception caught setting 'search' on 'class demo.ItemSearchAction: Error setting expression 'search' with value ['search', ] |
| Error setting expression 'search' with value ['search', ] - [unknown location] |
| at com.opensymphony.xwork2.ognl.OgnlValueStack.handleRuntimeException(OgnlValueStack.java:201) |
| at com.opensymphony.xwork2.ognl.OgnlValueStack.setValue(OgnlValueStack.java:178) |
| at com.opensymphony.xwork2.ognl.OgnlValueStack.setParameter(OgnlValueStack.java:152) |
| </code></pre></div></div> |
| |
| <p>Thus is expected behaviour to allow developer to spot missing setter or typo in either parameter name or setter.</p> |
| |
| <h3 id="examples">Examples</h3> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><action</span> <span class="na">name=</span><span class="s">"someAction"</span> <span class="na">class=</span><span class="s">"com.examples.SomeAction"</span><span class="nt">></span> |
| <span class="nt"><interceptor-ref</span> <span class="na">name=</span><span class="s">"params"</span><span class="nt">/></span> |
| <span class="nt"><result</span> <span class="na">name=</span><span class="s">"success"</span><span class="nt">></span>good_result.ftl<span class="nt"></result></span> |
| <span class="nt"></action></span> |
| </code></pre></div></div> |
| |
| </section> |
| </article> |
| |
| |
| <footer class="container"> |
| <div class="col-md-12"> |
| Copyright © 2000-2022 <a href="https://www.apache.org/">The Apache Software Foundation</a>. |
| Apache Struts, Struts, Apache, the Apache feather logo, and the Apache Struts project logos are |
| trademarks of The Apache Software Foundation. All Rights Reserved. |
| </div> |
| <div class="col-md-12">Logo and website design donated by <a href="https://softwaremill.com/">SoftwareMill</a>.</div> |
| </footer> |
| |
| <script>!function (d, s, id) { |
| var js, fjs = d.getElementsByTagName(s)[0]; |
| if (!d.getElementById(id)) { |
| js = d.createElement(s); |
| js.id = id; |
| js.src = "//platform.twitter.com/widgets.js"; |
| fjs.parentNode.insertBefore(js, fjs); |
| } |
| }(document, "script", "twitter-wjs");</script> |
| <script src="https://apis.google.com/js/platform.js" async="async" defer="defer"></script> |
| |
| <div id="fb-root"></div> |
| |
| <script>(function (d, s, id) { |
| var js, fjs = d.getElementsByTagName(s)[0]; |
| if (d.getElementById(id)) return; |
| js = d.createElement(s); |
| js.id = id; |
| js.src = "//connect.facebook.net/en_GB/all.js#xfbml=1"; |
| fjs.parentNode.insertBefore(js, fjs); |
| }(document, 'script', 'facebook-jssdk'));</script> |
| |
| |
| </body> |
| </html> |