Refactoring for Struts2 security changes.

I recently upgraded my Struts2 version from to 2.3.16. There are a couple of important security upgrades in this update ( and so it is worth upgrading. One of the changes was to turn off Dynamic Method Invocation (DMI). I had been using this feature, so I found that most of my website stopped working with the new release.
I was using DMI by having a method attribute on a submit tag, ie
<s:form action=”register” method=”post”>
<s:submit method=”refreshCaptcha” key=”label.register.refresh” align=”center” />
With DMI turned off the default execute method is being called instead of the specified refreshCaptcha method.
If you’ve hit this problem your options for getting this working again are

1. NOT RECOMMENDED. Turn DMI back on again. Put
<constant name=”struts.enable.DynamicMethodInvocation” value=”true”/>
in your struts.xml file. The downside of this is that DMI is a security issue – so only do this if you don’t care about security.

2. Add the method attribute to the action definition in the struts.xml file.
<s:form action=”register-rc” method=”post”>
<s:submit key=”label.register.refresh” align=”center” />
and in struts.xml
<action name=”register-rc” class=”registerAction” method=”refreshCaptcha” >
<result name=”input” type=”tiles”>/public.register.tiles</result>
<result name=”error” type=”tiles”>/public.register.tiles</result>
<result name=”resent” type=”tiles”>/public.registersuccess.tiles</result>
The downside of this is that you then need a separate action definition for every method in your action class that you want to call. You also can’t use this approach if you have a form with two submits in it .

3. NOT RECOMMENDED. As an extension to 2 – you can make this work with forms with 2 submits if you put
<constant name=”struts.mapper.action.prefix.enabled” value=”true”/>
in your struts.xml file and then add a separate
attribute to one of the submits – and add a separate action definition to struts.xml. The downside of this is that setting struts.mapper.action.prefix.enabled to true is reintroducing another security issue. So only do this if you don’t care about security.

4. Use the name attribute on the submit tag rather than the method attribute. This is what I did in most cases. So change the submit tag to use name
<s:form action=”register” method=”post”>
<s:submit name=”refreshCaptcha” key=”label.register.refresh” align=”center” />

Create a boolean in your action class and a setter method
private boolean refreshCaptcha = false;

public void setRefreshCaptcha(boolean refreshCaptcha) {
//this.refreshCaptcha = refreshCaptcha;
this.refreshCaptcha = true;
Note: in the setter I am ignoring the value that is passed in and hardcoding the boolean to true. This is because false is passed in unless you use the value attribute on the submit tag. If you use the value attribute – ie
<s:submit name=”refreshCaptcha” value=”Get new picture” align=”center” />
the value of the attribute will be what is displayed on the button (which may not be what you want if you are using key) – and the set method will be called with a String
public void setRefreshCaptcha(String refreshCaptchaStr) {
//you could check for the value of the string – or you could
this.refreshCaptcha = true;
All I really need to know is that the method has been called – so hardcoding the value in the method is ok.
Then in your execute method add an if statement at the begining
public String execute() {
if (refreshCaptcha) {
return refreshCaptcha();
// rest of the execute method
There is a similar approach documented here – although I was never able to get a true value passed to my setter methods as described there.

This entry was posted in Uncategorized and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s