blob: 1610919c475e5f4e2b7966ae9f2ab4bf8c8c3c21 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="Date-Revision-yyyymmdd" content="20140918"/>
<meta http-equiv="Content-Language" content="en"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Http Session</title>
<link href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,400italic,600italic,700italic" rel="stylesheet" type="text/css">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<link href="/css/main.css" rel="stylesheet">
<link href="/css/custom.css" rel="stylesheet">
<link href="/css/syntax.css" rel="stylesheet">
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="/bootstrap/js/bootstrap.js"></script>
<script type="text/javascript" src="/js/community.js"></script>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/* We explicitly disable cookie tracking to avoid privacy issues */
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '41']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body>
<a href="https://github.com/apache/struts" class="github-ribbon">
<img decoding="async" loading="lazy" style="position: absolute; right: 0; border: 0;" width="149" height="149" src="https://github.blog/wp-content/uploads/2008/12/forkme_right_red_aa0000.png?resize=149%2C149" class="attachment-full size-full" alt="Fork me on GitHub" data-recalc-dims="1">
</a>
<header>
<nav>
<div role="navigation" class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" data-toggle="collapse" data-target="#struts-menu" class="navbar-toggle">
Menu
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="/index.html" class="navbar-brand logo"><img src="/img/struts-logo.svg"></a>
</div>
<div id="struts-menu" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Home<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/index.html">Welcome</a></li>
<li><a href="/download.cgi">Download</a></li>
<li><a href="/releases.html">Releases</a></li>
<li><a href="/announce-2023.html">Announcements</a></li>
<li><a href="http://www.apache.org/licenses/">License</a></li>
<li><a href="https://www.apache.org/foundation/thanks.html">Thanks!</a></li>
<li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy Policy</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Support<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/mail.html">User Mailing List</a></li>
<li><a href="https://issues.apache.org/jira/browse/WW">Issue Tracker</a></li>
<li><a href="/security.html">Reporting Security Issues</a></li>
<li><a href="/commercial-support.html">Commercial Support</a></li>
<li class="divider"></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Migration+Guide">Version Notes</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Security+Bulletins">Security Bulletins</a></li>
<li class="divider"></li>
<li><a href="/maven/project-info.html">Maven Project Info</a></li>
<li><a href="/maven/struts2-core/dependencies.html">Struts Core Dependencies</a></li>
<li><a href="/maven/struts2-plugins/modules.html">Plugin Dependencies</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Documentation<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/birdseye.html">Birds Eye</a></li>
<li><a href="/primer.html">Key Technologies</a></li>
<li><a href="/kickstart.html">Kickstart FAQ</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Home">Wiki</a></li>
<li class="divider"></li>
<li><a href="/getting-started/">Getting Started</a></li>
<li><a href="/security/">Security Guide</a></li>
<li><a href="/core-developers/">Core Developers Guide</a></li>
<li><a href="/tag-developers/">Tag Developers Guide</a></li>
<li><a href="/maven-archetypes/">Maven Archetypes</a></li>
<li><a href="/plugins/">Plugins</a></li>
<li><a href="/maven/struts2-core/apidocs/index.html">Struts Core API</a></li>
<li><a href="/tag-developers/tag-reference.html">Tag reference</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/FAQs">FAQs</a></li>
<li><a href="http://cwiki.apache.org/S2PLUGINS/home.html">Plugin registry</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Contributing<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/youatstruts.html">You at Struts</a></li>
<li><a href="/helping.html">How to Help FAQ</a></li>
<li><a href="/dev-mail.html">Development Lists</a></li>
<li class="divider"></li>
<li><a href="/submitting-patches.html">Submitting patches</a></li>
<li><a href="/builds.html">Source Code and Builds</a></li>
<li><a href="/coding-standards.html">Coding standards</a></li>
<li><a href="/contributors/">Contributors Guide</a></li>
<li class="divider"></li>
<li><a href="/release-guidelines.html">Release Guidelines</a></li>
<li><a href="/bylaws.html">PMC Charter</a></li>
<li><a href="/volunteers.html">Volunteers</a></li>
<li><a href="https://gitbox.apache.org/repos/asf?p=struts.git">Source Repository</a></li>
<li><a href="/updating-website.html">Updating the website</a></li>
</ul>
</li>
<li class="apache"><a href="http://www.apache.org/"><img src="/img/apache.png"></a></li>
</ul>
</div>
</div>
</div>
</nav>
</header>
<article class="container">
<section class="col-md-12">
<a class="edit-on-gh" href="https://github.com/apache/struts-site/edit/master/source/getting-started/http-session.md" title="Edit this page on GitHub">Edit on GitHub</a>
<a href="index.html" title="back to Getting started"><< back to Getting started</a>
<h1 class="no_toc" id="http-session">HTTP Session</h1>
<ul id="markdown-toc">
<li><a href="#introduction" id="markdown-toc-introduction">Introduction</a></li>
<li><a href="#sessionaware-interface" id="markdown-toc-sessionaware-interface">SessionAware Interface</a></li>
<li><a href="#using-the-http-session-object-in-the-action-class" id="markdown-toc-using-the-http-session-object-in-the-action-class">Using the HTTP Session Object In The Action Class</a></li>
<li><a href="#accessing-http-session-objects-in-the-view" id="markdown-toc-accessing-http-session-objects-in-the-view">Accessing HTTP Session Objects In The View</a></li>
<li><a href="#best-practices-when-using-sessionaware" id="markdown-toc-best-practices-when-using-sessionaware">Best Practices When Using SessionAware</a></li>
<li><a href="#summary" id="markdown-toc-summary">Summary</a></li>
</ul>
<p>The example code for this tutorial, <strong>http-session</strong>, is available at <a href="https://github.com/apache/struts-examples">struts-examples</a>.</p>
<h2 id="introduction">Introduction</h2>
<p>Your Struts 2 application may need to access the HTTP session object. Struts 2 provides an interface,
<a href="/maven/struts2-core/apidocs/org/apache/struts2/interceptor/SessionAware">SessionAware</a>, that your Action class
should implement to obtain a reference to the HTTP session object.</p>
<p>The <a href="http://struts.apache.org/mail">Struts 2 user mailing list</a> is an excellent place to get help. If you are
having a problem getting the tutorial example applications to work search the Struts 2 mailing list. If you don’t find
an answer to your problem, post a question on the mailing list.</p>
<h2 id="sessionaware-interface">SessionAware Interface</h2>
<p>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:</p>
<p><strong>HelloWorldAction.java setSession Method</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">private</span> <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;</span> <span class="n">userSession</span> <span class="o">;</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setSession</span><span class="o">(</span><span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Object</span><span class="o">&gt;</span> <span class="n">session</span><span class="o">)</span> <span class="o">{</span>
<span class="n">userSession</span> <span class="o">=</span> <span class="n">session</span> <span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>
<p>The Struts 2 framework has an interceptor that will inject the HTTP session object into the Action class by calling
the <code class="language-plaintext highlighter-rouge">setSession</code> method.</p>
<h2 id="using-the-http-session-object-in-the-action-class">Using the HTTP Session Object In The Action Class</h2>
<p>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.</p>
<p><strong>HelloWorldAction.java increaseHelloCount Method</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">private</span> <span class="kt">void</span> <span class="nf">increaseHelloCount</span><span class="o">()</span> <span class="o">{</span>
<span class="nc">Integer</span> <span class="n">helloCount</span> <span class="o">=</span> <span class="o">(</span><span class="nc">Integer</span><span class="o">)</span> <span class="n">userSession</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="no">HELLO_COUNT</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">helloCount</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">)</span> <span class="o">{</span>
<span class="n">helloCount</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
<span class="n">helloCount</span><span class="o">++;</span>
<span class="o">}</span>
<span class="n">userSession</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="no">HELLO_COUNT</span><span class="o">,</span> <span class="n">helloCount</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>
<p>When the increaseHelloCount method is called from within the execute method, the userSession object is a reference
to the HTTP session object injected by the Struts 2 framework. So any objects stored in the HTTP session can be retrieved
using the userSession object and any objects stored in the userSession object will be stored in the HTTP session object.</p>
<h2 id="accessing-http-session-objects-in-the-view">Accessing HTTP Session Objects In The View</h2>
<p>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 <code class="language-plaintext highlighter-rouge">HelloWorld.jsp</code> with this markup:</p>
<p><strong>HelloWorld.jsp Get helloCount Value From HTTP Session</strong></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt">&lt;p&gt;</span>I've said hello to you <span class="nt">&lt;s:property</span> <span class="na">value=</span><span class="s">"#session.helloCount"</span> <span class="nt">/&gt;</span> times!<span class="nt">&lt;/p&gt;</span>
</code></pre></div></div>
<p>The <code class="language-plaintext highlighter-rouge">s:property</code> tag’s value attribute has a value of <code class="language-plaintext highlighter-rouge">#session.helloCount</code>. The “#” before the word session tells
the Struts framework to look in the session scope for a key of “helloCount” (which is the value of the String constant
<code class="language-plaintext highlighter-rouge">HELLO_COUNT</code> referenced in method <code class="language-plaintext highlighter-rouge">increaseHelloCount</code>). Struts will get the object mapped to <code class="language-plaintext highlighter-rouge">helloCount</code> key and
then call that object’s toString method to determine what to display in the view page.</p>
<h2 id="best-practices-when-using-sessionaware">Best Practices When Using SessionAware</h2>
<p>Using SessionAware does introduce a potential security vulnerability that you should mitigate by also following these
practices in the Action class that implements the SessionAware interface.</p>
<ol>
<li>Do not have a public <code class="language-plaintext highlighter-rouge">Map&lt;String, Object&gt; getSession</code> method in the Action class. You only need a public void
<code class="language-plaintext highlighter-rouge">setSession</code> method to implement the <code class="language-plaintext highlighter-rouge">SessionAware</code> interface.</li>
<li>Also have the Action class implement the <a href="/maven/struts2-core/apidocs/com/opensymphony/xwork2/interceptor/ParameterNameAware">ParameterNameAware interface</a>
and override its acceptableParameterName method:</li>
</ol>
<p><strong>HelloWorldAction.java acceptableParameterName Method</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">acceptableParameterName</span><span class="o">(</span><span class="nc">String</span> <span class="n">parameterName</span><span class="o">)</span> <span class="o">{</span>
<span class="kt">boolean</span> <span class="n">allowedParameterName</span> <span class="o">=</span> <span class="kc">true</span> <span class="o">;</span>
<span class="k">if</span> <span class="o">(</span> <span class="n">parameterName</span><span class="o">.</span><span class="na">contains</span><span class="o">(</span><span class="s">"session"</span><span class="o">)</span> <span class="o">||</span> <span class="n">parameterName</span><span class="o">.</span><span class="na">contains</span><span class="o">(</span><span class="s">"request"</span><span class="o">)</span> <span class="o">)</span> <span class="o">{</span>
<span class="n">allowedParameterName</span> <span class="o">=</span> <span class="kc">false</span> <span class="o">;</span>
<span class="o">}</span>
<span class="k">return</span> <span class="n">allowedParameterName</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>
<p>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.</p>
<p>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 <code class="language-plaintext highlighter-rouge">struts-default</code> set of interceptors as follows:</p>
<p><strong>struts.xml configure params interceptor</strong></p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;package</span> <span class="na">name=</span><span class="s">"basicstruts2"</span> <span class="na">extends=</span><span class="s">"struts-default"</span><span class="nt">&gt;</span>
<span class="nt">&lt;interceptors&gt;</span>
<span class="nt">&lt;interceptor-stack</span> <span class="na">name=</span><span class="s">"appDefault"</span><span class="nt">&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"defaultStack"</span><span class="nt">&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"exception.logEnabled"</span><span class="nt">&gt;</span>true<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"exception.logLevel"</span><span class="nt">&gt;</span>ERROR<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"params.excludeParams"</span><span class="nt">&gt;</span>dojo..*,^struts..*,^session..*,^request..*,^application..*,^servlet(Request|Response)..*,parameters...*<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;/interceptor-ref&gt;</span>
<span class="nt">&lt;/interceptor-stack&gt;</span>
<span class="nt">&lt;/interceptors&gt;</span>
<span class="nt">&lt;default-interceptor-ref</span> <span class="na">name=</span><span class="s">"appDefault"</span> <span class="nt">/&gt;</span>
...
<span class="nt">&lt;/package&gt;</span>
</code></pre></div></div>
<p>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 <code class="language-plaintext highlighter-rouge">params.excludeParams</code> node.</p>
<p>The example project includes both methods for mitigating the SessionAware security vulnerability.</p>
<blockquote>
<p>Note the same issue exists if you implement the ServletRequestAware interface, which is why the above method returns
false if the parameter name contains “request”.</p>
</blockquote>
<h2 id="summary">Summary</h2>
<p>When your Action class needs to access the HTTP session object implement the SessionAware interface and override
the <code class="language-plaintext highlighter-rouge">setSession</code> method. Be sure to also implement the <code class="language-plaintext highlighter-rouge">ParameterNameAware</code> interface and override
the <code class="language-plaintext highlighter-rouge">acceptableParameterName</code> method to mitigate a potential security vulnerability. If you have multiple actions
that implement <code class="language-plaintext highlighter-rouge">SessionAware</code> then consider modifying the params interceptor’s <code class="language-plaintext highlighter-rouge">excludeParams</code> value as part of your
Struts 2 package setup.</p>
<table>
<tbody>
<tr>
<td>Return to <a href="unit-testing">Unit Testing</a></td>
<td>or</td>
<td>onward to <a href="preperable-interface">Preparable Interface</a></td>
</tr>
</tbody>
</table>
</section>
</article>
<footer class="container">
<div class="col-md-12">
Copyright &copy; 2000-2022 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
Apache Struts, Struts, Apache, the Apache feather logo, and the Apache Struts project logos are
trademarks of The Apache Software Foundation. All Rights Reserved.
</div>
<div class="col-md-12">Logo and website design donated by <a href="https://softwaremill.com/">SoftwareMill</a>.</div>
</footer>
<script>!function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (!d.getElementById(id)) {
js = d.createElement(s);
js.id = id;
js.src = "//platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
}
}(document, "script", "twitter-wjs");</script>
<script src="https://apis.google.com/js/platform.js" async="async" defer="defer"></script>
<div id="fb-root"></div>
<script>(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s);
js.id = id;
js.src = "//connect.facebook.net/en_GB/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
</body>
</html>