Global interceptor - runs before every action - struts2

How can I create an interceptor that will run before EVERY action in my application, without the need to specify it for every action separately?

From http://struts.apache.org/2.3.4.1/docs/how-do-we-configure-an-interceptor-to-be-used-with-every-action.html:
Create your own named stacks and declare a new default interceptor stack for a package
<package name="default" extends="struts-default" >
<interceptors>
<interceptor-stack name="myStack">
<interceptor-ref name="timer"/>
<interceptor-ref name="logger"/>
<interceptor-ref name="default-stack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack"/>
<action name="login" class="tutorial.Login">
<result name="input">login.jsp</result>
<result type="redirect-action">/secure/home</result>
</action>
</package>

Related

Struts 2 interceptor firing when it shouldn't

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-default is a package with no actions, just to define the
interceptors and a couple stacks, in order to inherit from it.
numeritos-login is a package that inherits directly from
struts-default and, hence, uses the defaultStack from struts.
numeritos-secure inherits from numeritos-default and SHOULD (afaik)
use the numeritos-default default stack.
numeritos-admin inherits
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>
Defining package configuration elements are only for adding additional configuration to packages that extend it. The packages can contain interceptors, interceptor stacks, actions that can be extended.
The package element has one required attribute name, which acts as the key for later reference to the package. The extends attribute is optional and allows one package to inherit the configuration of one or more previous packages
including all interceptor, interceptor-stack, and action configurations.
Usually packages are separated by namespace attribute which is essential for configuring actions. You can define the abstract package which doesn't contain the action configurations.
The optional abstract attribute creates a base package that can omit the action configuration.
The thing is, you are not using namespace, nor abstract packages and default-intercepto-ref is not inherited to the packages that extends it.

Struts 2 File upload works fine in Chrome and Firefox but not in IE

I am having issue with struts 2 file upload for excel file in Internet explorer. It works fine in Chrome and firefox, but I am not sure what I am missing for IE.
Here is the struts config I have:
<action name="uploadAction" method="submitServiceProfile" class="serviceProfileAction">
<!-- <interceptor-ref name="exception"/>
<interceptor-ref name="i18n"/> -->
<interceptor-ref name="fileUpload">
<param name="allowedTypes">application/ms-excel,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</param>
<!-- <param name="maximumSize">20480</param> -->
</interceptor-ref>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*</param>
</interceptor-ref>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="store">
<param name="operationMode">STORE</param>
</interceptor-ref>
<interceptor-ref name="someStack"/>
<result name="success" type="redirectAction">managerPage</result>
<result name="error" type="redirectAction">managerPage</result>
<result name="input" type="tiles">homepage</result>
</action>
As suggested by user497087 (Thank you!), I completely removed allowedTypes, plus the interceptor-ref "fileupload". Now, the request gets to the action without a problem at any given browser.

Change Struts2 interceptor error messages

I am using Struts 2 + Hibernate (full-hibernate-plugin-for-struts2), and I have this code to check if image to upload is png:
struts.xml
<struts>
<package name="mypack" namespace="/" extends="hibernate-default">
...
<action name="myaction" class="com.actions.MyAction" >
<interceptor-ref name="defaultStackHibernate">
<param name="fileUpload.allowedTypes">image/png</param>
</interceptor-ref>
<result name="success" type="tiles" >baseLayout</result>
<result name="error" type="tiles" >error</result>
<result name="input" type="tiles" >baseLayout</result>
</action>
...
</package>
</struts>
The error message that comes out if I upload not allowed image types is:
Content-Type not allowed: image "img.jpg" "upload__2988a871_13b93535e21__7fc1_00000009.tmp" image/jpeg
How can I modify that error message? Using something like "hibernate-messages.properties"?
You can override this message by creating text for this key:
struts.messages.error.content.type.not.allowed

Cannot exclude method in struts2 interceptor

I am having the opposite problem of the fellow in this question:
Struts 2: excluding method from validation from just the defaultStack interceptor
The above question involved all methods being excluded, my issue is that no methods are being excluded!
I'm trying to get my authenticationInterceptor to ignore the showLogin method of my LoginAction:
<interceptors>
<interceptor name="authorizationInterceptor" class="org.companyname.struts.interceptor.AuthorizationInterceptor"/>
<interceptor-stack name="appDefault">
<interceptor-ref name="authorizationInterceptor"/>
<interceptor-ref name="defaultStack">
<param name="exception.logEnabled">true</param>
<param name="exception.logLevel">ERROR</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="appDefault" />
<action name="loginInitial" class="org.companyname.struts.action.LoginAction" method="showLogin">
<interceptor-ref name="appDefault">
<param name="authorizationInterceptor.excludeMethods">showLogin</param>
</interceptor-ref>
<result name="success">/login.jsp</result>
</action>
However, each time I forward to loginInitial, the interceptor grabs it, even though my showLogin method is being excluded.
I've checked for naming issues, and have tried putting several different values in the interceptor-ref within the action, and nothing seems to work.
What's the proper way to skip the authorizationInterceptor when I forward to loginIntial?
I believe my issue is the type of interceptor I'm using, the AbstractInterceptor. So, I just use different interceptor stacks on the actions I don't want intercepted:
<interceptor-stack name="appDefaultWithAuth">
<interceptor-ref name="defaultStack">
<param name="exception.logEnabled">true</param>
<param name="exception.logLevel">ERROR</param>
</interceptor-ref>
<interceptor-ref name="authorizationInterceptor"/>
</interceptor-stack>
<interceptor-stack name="appDefaultNoAuth">
<interceptor-ref name="defaultStack">
<param name="exception.logEnabled">true</param>
<param name="exception.logLevel">ERROR</param>
</interceptor-ref>
</interceptor-stack>
<default-interceptor-ref name="appDefaultWithAuth" />
<action name="loginInitial" class="org.company.struts.action.LoginAction" method="showLogin">
<interceptor-ref name="appDefaultNoAuth"/>
<result name="success">/login.jsp</result>
</action>

Skipping default interceptor stack only on specific class

Hi
We have created a customized interceptor stack called appInterceptorStack and referred it as a <default-interceptor-ref name="appInterceptorStack"/>,
appInterceptorStack -> dont have validation and workflow interceptors attached to them.
But now for a specific action class I need to use validate method so I need validation interceptor
I created a new Interceptor stack with validation and workflow interceptors and referred it from action class. But only the default interceptor stack is getting executed. The changed one is not getting called, Please find the sample code below.
<package name="default" extends="struts-default">
<interceptor-stack name=”AppStack”>
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="params"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="params"/>
</interceptor-stack>
<interceptor-stack name=”GuiStack”>
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="params"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="params"/>
<interceptor-ref name="validation" />
<interceptor-ref name="workflow" />
</interceptor-stack>
<default-interceptor-ref name="AppStack"/>
<action name="test" class="com.jranch.Test">
<interceptor-ref name="GuiStack”/>
<result name="input">login.jsp</result>
<result name="success" type="redirect-action">/secure/home</result>
</action>
</package>
Can someone please help me?
The configuration looks correct. Can you turn on debug logging for com.opensymphony.
You can then see the interceptors being called in turn. This is the quickest way of seeing what is being called.

Resources