Info |
---|
The example code for this tutorial, HTTP_Session_Struts2_Mvnhttp_session, is available on Google Code - httpat https://code.googlegithub.com/papache/struts2-examples/downloads/list. After downloading and unzipping the file, you'll have a folder named HTTP_Session_Struts2_Mvn. In that folder will be a README.txt file with instructions on now to build and run the example application.struts-examples |
Introduction
Your Struts 2 application may need to access the HTTP session object. Struts 2 provides an interface, SessionAware, that your Action class should implement to obtain a reference to the HTTP session object.
...
The SessionAware interface has one method, setSession, that your Action class will need to override. In the example application (see above), the HelloWorldAction class implements the SessionAware interface and includes this code:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
private Map<String, Object> userSession ;
public void setSession(Map<String, Object) session) {
userSession = session ;
}
|
...
The example application keeps track of how many times the user clicks on a Hello link or submits the hello form. It stores this count in the HTTP session object in the increaseHelloCount method.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
private void increaseHelloCount() {
Integer helloCount = (Integer) userSession.get(HELLO_COUNT);
if (helloCount == null ) {
helloCount = 1;
} else {
helloCount++;
}
userSession.put(HELLO_COUNT, helloCount);
}
|
...
Struts 2 provides an easy way to get an object stored in the HTTP session from within the view page. In the example application is HelloWorld.jsp with this markup:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<p>I've said hello to you <s:property value="#session.helloCount" /> times!</p>
|
The s:property tag's value attribute has a value of #session.helloCount. The "#" before the word session tells the Struts framework to look in the session scope for the a key of "helloCount" (which is the value of the String constant HELLO_COUNT referenced in method increaseHelloCount). Struts will get the object mapped to helloCount key and then call that object's toString method to determine what to display in the view page.
...
Using SessionAware does introduce a potential security vulnerability that you should mitigate by also following these practices in you the Action class that implements the SessionAware interface.
- Do not have a public Map<String, Object) getSession method in your the Action class. You only need a public void setSession method to implement the SessionAware interface.
- Also have your the Action class implement the ParameterNameAware interface and override its acceptableParameterName method:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
public boolean acceptableParameterName(String parameterName) {
boolean allowedParameterName = true ;
if ( parameterName.contains("session") || parameterName.contains("request") ) {
allowedParameterName = false ;
}
return allowedParameterName;
}
|
This method will be called by the Struts 2 framework for each parameter in the request scope. By returning false if the parameter name contains "session" we are telling the Struts 2 framework to ignore that parameter. This will prevent a malicious user from trying to hack the HTTP session object.
Instead of having each action that implements SessionAware also implement the ParameterNameAware interface you can tell the params interceptor to exclude specific request attributes for all actions in a package. In struts.xml configure the struts-default set of interceptors as follows:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<package name="basicstruts2" extends="struts-default"> <interceptors> <interceptor-stack name="appDefault"> <interceptor-ref name="defaultStack"> <param name="exception.logEnabled">true</param> <param name="exception.logLevel">ERROR</param> <param name="params.excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param> </interceptor-ref> </interceptor-stack> </interceptors> <default-interceptor-ref name="appDefault" /> |
The above code will ensure that every action in the "basicstruts2" package that implements the SessionAware interface will exclude from processing parameters that starts with the strings provided in the params.excludeParams noded.
The example project includes both methods for mitigating the SessionAware security vulnerability.
Tip |
---|
Note the same issue exists if you implement the ServletRequestAware interface, which is way why the above method returns false if the parameter name contains "request". |
...
When your Action class needs to access the HTTP session object implement the SessionAware interface and override the setSession method. Be sure to also implement the ParameterNameAware interface and override the acceptableParameterName method to mitigate a potential security vulnerability. If you have multiple actions that implement SessionAware then consider modifying the params interceptor's excludeParams value as part of your Struts 2 package setup.