Home > Guides > Core Developers Guide > Security

Security tips

The Apache Struts 2 doesn't provide any security mechanism - it is just a pure web framework. Below are few tips you should consider during application development with the Apache Struts 2.

Restrict access to the Config Browser

Config Browser Plugin exposes internal configuration and should be used only during development phase. If you must use it on production site, we strictly recommend restricting access to it - you can use  Basic Authentication or any other security mechanism (e.g. Apache Shiro)

Don't mix different access levels in the same namespace

Very often access to different resources is controlled based on URL patterns, see snippet below. Because of that you cannot mix actions with different security levels in the same namespace. Always group actions in one namespace by security level.

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>admin</web-resource-name>
            <url-pattern>/secure/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>

Never expose JSP files directly

You must always hide JSP file behind an action, you cannot allow for direct access to the JSP files as this can leads to unpredictable security vulnerabilities. You can achieve this by putting all your JSP files under the WEB-INF folder - most of the JEE containers restrict access to files placed under the WEB-INF folder. Second option is to add security constraint to the web.xml file:

<!-- Restricts access to pure JSP files - access available only via Struts action -->
<security-constraint>
    <display-name>No direct JSP access</display-name>
    <web-resource-collection>
        <web-resource-name>No-JSP</web-resource-name>
        <url-pattern>*.jsp</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>no-users</role-name>
    </auth-constraint>
</security-constraint>

<security-role>
    <description>Don't assign users to this role</description>
    <role-name>no-users</role-name>
</security-role>

The best approach is to used the both solutions.

Internal security mechanism

The Apache Struts 2 contains internal security manager which blocks access to particular classes and Java packages - it's a OGNL-wide mechanism which means it affects any aspect of the framework ie. incoming parameters, expressions used in JSPs, etc.

The defaults are as follow:

    <constant name="struts.excludedClasses"
              value="
                java.lang.Object,
                java.lang.Runtime,
                java.lang.System,
                java.lang.Class,
                java.lang.ClassLoader,
                java.lang.Shutdown,
                ognl.OgnlContext,
                ognl.MemberAccess,
                ognl.ClassResolver,
                ognl.TypeConverter,
                com.opensymphony.xwork2.ActionContext" />
    <!-- this must be valid regex, each '.' in package name must be escaped! -->
    <constant name="struts.excludedPackageNamePatterns" value="^java\.lang\..*,^ognl.*,^javax.*" />

Any expression or target which evaluates to one of these will be blocked and you see a WARN in logs:

[WARNING] Target class [class example.MyBean] or declaring class of member type [public example.MyBean()] are excluded!

In that case new MyBean() was used to create a new instance of class (inside JSP) - it's blocked because target of such expression is evaluated to java.lang.Class

It is possible to redefine the above constants in struts.xml but try to avoid this and rather change design of your application!

Accessing static methods

Support for accessing static methods from expression will be disabled soon, please consider re-factoring your application to avoid further problems! Please check WW-4348.

OGNL is used to call action's methods

This can impact actions which have large inheritance hierarchy and use the same method's name throughout the hierarchy, this was reported as an issue WW-4405. See the example below:

public class RealAction extends BaseAction {  
    @Action("save")
    public String save() throws Exception {
        super.save();
        return SUCCESS;
    }
}    
 
public class BaseAction extends AbstractAction {
    public String save() throws Exception {
        save(Double.MAX_VALUE);
        return SUCCESS;
    }
}
 
public abstract class AbstractAction extends ActionSupport {
    protected void save(Double val) {
        // some logic
    }
}

In such case OGNL cannot properly map which method to call when request is coming. This is do the OGNL limitation. To solve the problem don't use the same method's names through the hierarchy, you can simply change the action's method from save() to saveAction() and leaving annotation as is to allow call this action via /save.action request.

Accepted / Excluded patterns

As from version 2.3.20 the framework provides two new interfaces which are used to accept / exclude param names and values - AcceptedPatternsChecker and ExcludedPatternsChecker with default implementations. These two interfaces are used by Parameters Interceptor and Cookie Interceptor to check if param can accepted or must be excluded. If you were using excludeParams previously please compare patterns used by you with these provided by the framework in default implementation.