I have different areas in my webapp, basically:
- Login actions. No special interceptor needs.
- Secure zone. Only for authenticated users. AuthenticationInterceptor redirects non authenticated users to logout action.
- Admin zone. Only for admin users. AdministrationInterceptor redirects non admin users to logout action.
Hence, I have divided my actions in packages.
numeritos-defaultis a package with no actions, just to define the interceptors and a couple stacks, in order to inherit from it.numeritos-loginis a package that inherits directly from struts-default and, hence, uses the defaultStack from struts.numeritos-secureinherits from numeritos-default and SHOULD (afaik) use the numeritos-default default stack.numeritos-admininherits from numeritos-default but defines a different default stack, in order to add the administrationInterceptor to the default stack.
The thing is, the actions in numeritos-secure are executing the administrationInterceptor when they shouldn't, since their default stack, inherited from numeritos-default doesn't include that interceptor (I can't figure out the reason), hence only admin users can access the application. The rest of users are kicked out of the whole secure zone, when they should be only kicked out of the admin zone.
I have the following struts.xml configuration file. Sorry to post the whole of it, but I think it could help. All classes references are really Spring beans names, since all dependencies are managed by Spring.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<constant name="struts.custom.i18n.resources" value="global-messages" />
<constant name="struts.devMode" value="true" />
<constant name="struts.ui.theme" value="simple" />
<package name="numeritos-default" extends="struts-default">
<interceptors>
<!-- Session authentication interceptor -->
<interceptor name="authenticationInterceptor" class="authenticationInterceptor"/>
<!-- Administration privileges interceptor -->
<interceptor name="administrationInterceptor" class="administrationInterceptor"/>
<!-- Caching headers interceptor -->
<interceptor name="cachingHeadersInterceptor" class="cachingHeadersInterceptor"/>
<!-- Default interceptor stack for this package (default + authentication) -->
<interceptor-stack name="numeritosDefaultStack">
<interceptor-ref name="authenticationInterceptor"/>
<interceptor-ref name="cachingHeadersInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
<!-- Default interceptor stack for administration packages (default + administration) -->
<interceptor-stack name="numeritosAdminStack">
<interceptor-ref name="administrationInterceptor"/>
<interceptor-ref name="numeritosDefaultStack"/>
</interceptor-stack>
</interceptors>
<!-- Secure interceptor stack as default -->
<default-interceptor-ref name="numeritosDefaultStack"/>
</package>
<package name="numeritos-login" extends="struts-default">
<action name="welcome" class="welcomeAction">
<result name="success" type="freemarker">ftl/login.ftl</result>
</action>
<action name="login" class="loginAction">
<result name="success" type="redirectAction">exerciseLoad</result>
<result name="input" type="freemarker">ftl/login.ftl</result>
</action>
</package>
<package name="numeritos-secure" extends="numeritos-default">
<!-- Common login result -->
<global-results>
<result name="login" type="redirectAction">logout</result>
</global-results>
<action name="exerciseLoad" class="exerciseLoadAction">
<result name="simple_op" type="freemarker">ftl/simple_operation_view.ftl</result>
<result name="equation" type="freemarker">ftl/equation_view.ftl</result>
</action>
<action name="exerciseCheck" class="exerciseCheckAction">
<result name="success" type="freemarker">ftl/show_exercise_result.ftl</result>
<result name="input" type="freemarker">ftl/answer_format_error.ftl</result>
</action>
<action name="stats" class="statsAction">
<result name="success" type="freemarker">ftl/stats.ftl</result>
</action>
<action name="modulesList" class="modulesListAction">
<result name="success" type="freemarker">ftl/modules_list.ftl</result>
</action>
<action name="selectModule" class="selectModuleAction">
<result name="input" type="freemarker">ftl/modules_list.ftl</result>
<result name="success" type="redirectAction">exerciseLoad</result>
</action>
<action name="userSettings" class="userSettingsAction">
<result name="success" type="freemarker">ftl/user_settings.ftl</result>
</action>
<action name="changePassword" class="changePasswordAction">
<result name="success" type="freemarker">ftl/user_settings.ftl</result>
<result name="input" type="freemarker">ftl/user_settings.ftl</result>
</action>
<action name="logout" class="logoutAction">
<result name="success" type="freemarker">ftl/login.ftl</result>
</action>
</package>
<package name="numeritos-admin" extends="numeritos-secure">
<!-- Admin interceptor stack as default -->
<default-interceptor-ref name="numeritosAdminStack"/>
<!-- Common login result -->
<global-results>
<result name="login" type="redirectAction">logout</result>
</global-results>
<action name="adminConsole" class="adminConsoleAction">
<result name="success" type="freemarker">ftl/admin_console_results.ftl</result>
</action>
<action name="adminConsoleGroups" class="adminConsoleGroupsAction">
<result name="success" type="freemarker">ftl/admin_console_groups.ftl</result>
</action>
<action name="adminCreateGroup" class="adminConsoleGroupsAction" method="create">
<result name="success" type="redirectAction">adminConsoleGroups</result>
</action>
<action name="adminDeleteGroup" class="adminConsoleGroupsAction" method="delete">
<result name="success" type="redirectAction">adminConsoleGroups</result>
</action>
</package>
<package name="json-admin" extends="numeritos-default, json-default">
<interceptors>
<!-- Default interceptor stack for this package (default + administration + json) -->
<interceptor-stack name="numeritosJsonAdminStack">
<interceptor-ref name="administrationInterceptor"/>
<interceptor-ref name="json"/>
<interceptor-ref name="numeritosDefaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="numeritosJsonAdminStack"/>
<action name="jsonTest" class="jsonTestAction">
<result name="success" type="json">
<param name="root">users</param>
</result>
</action>
</package>
</struts>