blob: a745433677be5efa18a2880faae45b2625bdb652 [file]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(["setDoNotTrack", true]);
_paq.push(["disableCookies"]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '79']);
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 -->
<title>11 Security 1.3.9</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" href="../css/main.css" type="text/css" media="screen, print" title="Style" charset="utf-8"/>
<link rel="stylesheet" href="../css/pdf.css" type="text/css" media="print" title="PDF" charset="utf-8"/>
<script type="text/javascript">
function addJsClass() {
var classes = document.body.className.split(" ");
classes.push("js");
document.body.className = classes.join(" ");
}
</script>
</head>
<body class="body" onload="addJsClass();">
<div id="navigation">
<ul>
<li>
<div id="nav-summary" onmouseover="toggleNavSummary(false)" onmouseout="toggleNavSummary(true)">
<a href="../guide/index.html" class="button">Table of contents</a>
<div id="nav-summary-childs" style="display:none;">
<div class="toc-item" style="margin-left:0"><a href="../guide/1.%20Introduction.html"><strong>1</strong><span>Introduction</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/2.%20Getting%20Started.html"><strong>2</strong><span>Getting Started</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/3.%20Configuration.html"><strong>3</strong><span>Configuration</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/4.%20The%20Command%20Line.html"><strong>4</strong><span>The Command Line</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/5.%20Object%20Relational%20Mapping%20(GORM).html"><strong>5</strong><span>Object Relational Mapping (GORM)</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/6.%20The%20Web%20Layer.html"><strong>6</strong><span>The Web Layer</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/7.%20Validation.html"><strong>7</strong><span>Validation</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/8.%20The%20Service%20Layer.html"><strong>8</strong><span>The Service Layer</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/9.%20Testing.html"><strong>9</strong><span>Testing</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/10.%20Internationalization.html"><strong>10</strong><span>Internationalization</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/11.%20Security.html"><strong>11</strong><span>Security</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/12.%20Plug-ins.html"><strong>12</strong><span>Plug-ins</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/13.%20Web%20Services.html"><strong>13</strong><span>Web Services</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/14.%20Grails%20and%20Spring.html"><strong>14</strong><span>Grails and Spring</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/15.%20Grails%20and%20Hibernate.html"><strong>15</strong><span>Grails and Hibernate</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/16.%20Scaffolding.html"><strong>16</strong><span>Scaffolding</span></a>
</div>
<div class="toc-item" style="margin-left:0"><a href="../guide/17.%20Deployment.html"><strong>17</strong><span>Deployment</span></a>
</div>
</div>
</div>
</li>
<li class="separator selected">
<a id="ref-button" onclick="localToggle(); return false;" href="#">Quick Reference</a>
</li>
</ul>
</div>
<div id="header">
<div class="images clearfix">
<span id="logo"><a href="http://grails.org" target="_blank"><img alt="Grails Logo" title="The Grails Framework" src="../img/grails.png" border="0"/></a></span>
<span id="sponsor"><a href="http://springsource.com" target="_blank"><img alt="SpringSource Logo" title="SpringSource - Weapons for the War on Java Complexity" src="../img/springsource-logo.png" border="0"/></a></span>
</div>
<p>See the light - agile, industrial strength, rapid web application development made easy</p>
</div>
<table id="colset" border="0" cellpadding="0" cellspacing="0">
<tr>
<td id="col1">
<div id="main" class="corner-all">
<div class="toc-item prev-left"><a href="../guide/10.%20Internationalization.html">&lt;&lt; <strong>10</strong><span>Internationalization</span></a></div>
<span id='toggle-col1' class="toggle">(<a href="#" onclick="localToggle(); return false;">Quick Reference</a>)</span>
<div class="toc-item next-right"><a href="../guide/12.%20Plug-ins.html"><strong>12</strong><span>Plug-ins</span> >></a></div>
<div class="project">
<h1>11 Security - Reference Documentation</h1>
<p><strong>Authors:</strong> Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith</p>
<p><strong>Version:</strong> 1.3.9</p>
</div>
<div id="table-of-content">
<h2>Table of Contents</h2>
<div class="toc-item" style="margin-left:0px"><a href="#11.1%20Securing%20Against%20Attacks"><strong>11.1</strong><span>Securing Against Attacks</span></a>
</div>
<div class="toc-item" style="margin-left:0px"><a href="#11.2%20Encoding%20and%20Decoding%20Objects"><strong>11.2</strong><span>Encoding and Decoding Objects</span></a>
</div>
<div class="toc-item" style="margin-left:0px"><a href="#11.3%20Authentication"><strong>11.3</strong><span>Authentication</span></a>
</div>
<div class="toc-item" style="margin-left:0px"><a href="#11.4%20Security%20Plug-ins"><strong>11.4</strong><span>Security Plug-ins</span></a>
</div>
<div class="toc-item" style="margin-left:10px"><a href="#11.4.1%20Spring%20Security"><strong>11.4.1</strong><span>Spring Security</span></a>
</div>
<div class="toc-item" style="margin-left:10px"><a href="#11.4.2%20Shiro"><strong>11.4.2</strong><span>Shiro</span></a>
</div>
</div>
<h1 id="11. Security">11 Security</h1>
Grails is no more or less secure than Java Servlets. However, Java servlets (and hence Grails) are extremely secure and largely immune to common buffer overrun and malformed URL exploits due to the nature of the Java Virtual Machine underpinning the code.<p class="paragraph"/>Web security problems typically occur due to developer naivety or mistakes, and there is a little Grails can do to avoid common mistakes and make writing secure applications easier to write.<p class="paragraph"/><h4>What Grails Automatically Does</h4><p class="paragraph"/>Grails has a few built in safety mechanisms by default.
<ol>
<li>All standard database access via <a href="../guide/single.html#5.%20Object%20Relational%20Mapping%20(GORM)" class="guide">GORM</a> domain objects is automatically SQL escaped to prevent SQL injection attacks</li>
<li>The default <a href="../guide/single.html#16.%20Scaffolding" class="guide">scaffolding</a> templates HTML escape all data fields when displayed</li>
<li>Grails link creating tags (<a href="../ref/Tags/link.html" class="tags">link</a>, <a href="../ref/Tags/form.html" class="tags">form</a>, <a href="../ref/Tags/createLink.html" class="tags">createLink</a>, <a href="../ref/Tags/createLinkTo.html" class="tags">createLinkTo</a> and others) all use appropriate escaping mechanisms to prevent code injection</li>
<li>Grails provides <a href="../guide/single.html#11.2%20Encoding%20and%20Decoding%20Objects" class="guide">codecs</a> to allow you to trivially escape data when rendered as HTML, JavaScript and URLs to prevent injection attacks here.</li>
</ol><p class="paragraph"/>
<h2 id="11.1 Securing Against Attacks">11.1 Securing Against Attacks</h2>
<h4>SQL injection</h4><p class="paragraph"/>Hibernate, which is the technology underlying GORM domain classes, automatically escapes data when committing to database so this is not an issue. However it is still possible to write bad dynamic HQL code that uses unchecked request parameters. For example doing the following is vulnerable to HQL injection attacks:<p class="paragraph"/><div class="code"><pre>def vulnerable = &#123;
def books = Book.find(<span class="java&#45;quote">"from Book as b where b.title ='"</span> + params.title + <span class="java&#45;quote">"'"</span>)
&#125;</pre></div><p class="paragraph"/>Do <strong class="bold">not</strong> do this. If you need to pass in parameters use named or positional parameters instead:<p class="paragraph"/><div class="code"><pre>def safe = &#123;
def books = Book.find(<span class="java&#45;quote">"from Book as b where b.title =?"</span>, &#91;params.title&#93;)
&#125;</pre></div><p class="paragraph"/>Do <strong class="bold">not</strong> do this. Use named or positional parameters instead to pass in parameters:<p class="paragraph"/><div class="code"><pre>def safe() &#123;
def books = Book.find(<span class="java&#45;quote">"from Book as b where b.title = ?"</span>,
&#91;params.title&#93;)
&#125;</pre></div><p class="paragraph"/>or<p class="paragraph"/><div class="code"><pre>def safe() &#123;
def books = Book.find(<span class="java&#45;quote">"from Book as b where b.title = :title"</span>,
&#91;title: params.title&#93;)
&#125;</pre></div><p class="paragraph"/><h4>Phishing</h4><p class="paragraph"/>This really a public relations issue in terms of avoiding hijacking of your branding and a declared communication policy with your customers. Customers need to know how to identify bonafide emails received.<p class="paragraph"/><h4>XSS - cross-site scripting injection</h4><p class="paragraph"/>It is important that your application verifies as much as possible that incoming requests were originated from your application and not from another site. Ticketing and page flow systems can help this and Grails' support for <a href="http://www.springsource.org/webflow" target="blank">Spring Web Flow</a> includes security like this by default.<p class="paragraph"/>It is also important to ensure that all data values rendered into views are escaped correctly. For example when rendering to HTML or XHTML you must call <a href="../guide/single.html#11.2%20Encoding%20and%20Decoding%20Objects" class="guide">encodeAsHTML</a> on every object to ensure that people cannot maliciously inject JavaScript or other HTML into data or tags viewed by others. Grails supplies several <a href="../guide/single.html#11.2%20Encoding%20and%20Decoding%20Objects" class="guide">Dynamic Encoding Methods</a> for this purpose and if your output escaping format is not supported you can easily write your own codec.<p class="paragraph"/>You must also avoid the use of request parameters or data fields for determining the next URL to redirect the user to. If you use a <code>successURL</code> parameter for example to determine where to redirect a user to after a successful login, attackers can imitate your login procedure using your own site, and then redirect the user back to their own site once logged in, potentially allowing JS code to then exploit the logged-in account on the site.<p class="paragraph"/><h4>Cross-site request forgery</h4><p class="paragraph"/>CSRF involves unauthorized commands being transmitted from a user that a website trusts. A typical example would be another website embedding a link to perform an action on your website if the user is still authenticated.<p class="paragraph"/>The best way to decrease risk against these types of attacks is to use the <code>useToken</code> attribute on your forms. See <a href="../guide/single.html#6.1.11%20Handling%20Duplicate%20Form%20Submissions" class="guide">Handling Duplicate Form Submissions</a> for more information on how to use it. An additional measure would be to not use remember-me cookies.<p class="paragraph"/><h4>HTML/URL injection</h4><p class="paragraph"/>This is where bad data is supplied such that when it is later used to create a link in a page, clicking it will not cause the expected behaviour, and may redirect to another site or alter request parameters.<p class="paragraph"/>HTML/URL injection is easily handled with the <a href="../guide/single.html#11.2%20Encoding%20and%20Decoding%20Objects" class="guide">codecs</a> supplied by Grails, and the tag libraries supplied by Grails all use <a href="../guide/single.html#11.2%20Encoding%20and%20Decoding%20Objects" class="guide">encodeAsURL</a> where appropriate. If you create your own tags that generate URLs you will need to be mindful of doing this too.<p class="paragraph"/><h4>Denial of service</h4><p class="paragraph"/>Load balancers and other appliances are more likely to be useful here, but there are also issues relating to excessive queries for example where a link is created by an attacker to set the maximum value of a result set so that a query could exceed the memory limits of the server or slow the system down. The solution here is to always sanitize request parameters before passing them to dynamic finders or other GORM query methods:<p class="paragraph"/><div class="code"><pre>def safeMax = <span class="java&#45;object">Math</span>.max(params.max?.toInteger(), 100) // limit to 100 results
<span class="java&#45;keyword">return</span> Book.list(max:safeMax)</pre></div><p class="paragraph"/><h4>Guessable IDs</h4><p class="paragraph"/>Many applications use the last part of the URL as an "id" of some object to retrieve from GORM or elsewhere. Especially in the case of GORM these are easily guessable as they are typically sequential integers.<p class="paragraph"/>Therefore you must assert that the requesting user is allowed to view the object with the requested id before returning the response to the user.<p class="paragraph"/>Not doing this is "security through obscurity" which is inevitably breached, just like having a default password of "letmein" and so on.<p class="paragraph"/>You must assume that every unprotected URL is publicly accessible one way or another.
<h2 id="11.2 Encoding and Decoding Objects">11.2 Encoding and Decoding Objects</h2>
Grails supports the concept of dynamic encode/decode methods. A set of standard codecs are bundled with Grails. Grails also supports a simple mechanism for developers to contribute their own codecs that will be recognized at runtime.<p class="paragraph"/><h4>Codec Classes</h4><p class="paragraph"/>A Grails codec class is one that may contain an encode closure, a decode closure or both. When a Grails application starts up the Grails framework dynamically loads codecs from the <code>grails-app/utils/</code> directory.<p class="paragraph"/>The framework looks under <code>grails-app/utils/</code> for class names that end with the convention <code>Codec</code>. For example one of the standard codecs that ships with Grails is <code>HTMLCodec</code>.<p class="paragraph"/>If a codec contains an <code>encode</code> closure Grails will create a dynamic <code>encode</code> method and add that method to the <code>Object</code> class with a name representing the codec that defined the encode closure. For example, the <code>HTMLCodec</code> class defines an <code>encode</code> closure, so Grails attaches it with the name <code>encodeAsHTML</code>.<p class="paragraph"/>The <code>HTMLCodec</code> and <code>URLCodec</code> classes also define a <code>decode</code> closure, so Grails attaches those with the names <code>decodeHTML</code> and <code>decodeURL</code> respectively. Dynamic codec methods may be invoked from anywhere in a Grails application. For example, consider a case where a report contains a property called 'description' which may contain special characters that must be escaped to be presented in an HTML document. One way to deal with that in a GSP is to encode the description property using the dynamic encode method as shown below:<p class="paragraph"/><div class="code"><pre>$&#123;report.description.encodeAsHTML()&#125;</pre></div><p class="paragraph"/>Decoding is performed using <code>value.decodeHTML()</code> syntax.<p class="paragraph"/><h4>Standard Codecs</h4><p class="paragraph"/><strong class="bold">HTMLCodec</strong><p class="paragraph"/>This codec performs HTML escaping and unescaping, so that values can be rendered safely in an HTML page without creating any HTML tags or damaging the page layout. For example, given a value "Don't you know that 2 &#62; 1?" you wouldn't be able to show this safely within an HTML page because the &#62; will look like it closes a tag, which is especially bad if you render this data within an attribute, such as the value attribute of an input field.<p class="paragraph"/>Example of usage:<p class="paragraph"/><div class="code"><pre>&#60;input name=<span class="java&#45;quote">"comment.message"</span> value=<span class="java&#45;quote">"$&#123;comment.message.encodeAsHTML()&#125;"</span>/&#62;</pre></div><p class="paragraph"/>
<blockquote class="note">
Note that the HTML encoding does not re-encode apostrophe/single quote so you must use double quotes on attribute values to avoid text with apostrophes affecting your page.
</blockquote><p class="paragraph"/><strong class="bold">URLCodec</strong><p class="paragraph"/>URL encoding is required when creating URLs in links or form actions, or any time data is used to create a URL. It prevents illegal characters from getting into the URL and changing its meaning, for example "Apple &#38; Blackberry" is not going to work well as a parameter in a GET request as the ampersand will break parameter parsing.<p class="paragraph"/>Example of usage:<p class="paragraph"/><div class="code"><pre>&#60;a href=<span class="java&#45;quote">"/mycontroller/find?searchKey=$&#123;lastSearch.encodeAsURL()&#125;"</span>&#62;
Repeat last search
&#60;/a&#62;</pre></div><p class="paragraph"/>
<strong class="bold">Base64Codec</strong><p class="paragraph"/>Performs Base64 encode/decode functions. Example of usage:<p class="paragraph"/><div class="code"><pre>Your registration code is: $&#123;user.registrationCode.encodeAsBase64()&#125;</pre></div><p class="paragraph"/>
<strong class="bold">JavaScriptCodec</strong><p class="paragraph"/>Escapes Strings so they can be used as valid JavaScript strings. For example:<p class="paragraph"/><div class="code"><pre>Element.update('$&#123;elementId&#125;',
'$&#123;render(template: <span class="java&#45;quote">"/common/message"</span>).encodeAsJavaScript()&#125;')</pre></div><p class="paragraph"/>
<strong class="bold">HexCodec</strong><p class="paragraph"/>Encodes byte arrays or lists of integers to lowercase hexadecimal strings, and can decode hexadecimal strings into byte arrays. For example:<p class="paragraph"/><div class="code"><pre>Selected colour: &#35;$&#123;&#91;255,127,255&#93;.encodeAsHex()&#125;</pre></div><p class="paragraph"/>
<strong class="bold">MD5Codec</strong><p class="paragraph"/>Uses the MD5 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a lowercase hexadecimal string. Example of usage:<p class="paragraph"/><div class="code"><pre>Your API Key: $&#123;user.uniqueID.encodeAsMD5()&#125;</pre></div><p class="paragraph"/><strong class="bold">MD5BytesCodec</strong><p class="paragraph"/>Uses the MD5 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a byte array. Example of usage:<p class="paragraph"/><div class="code"><pre><span class="java&#45;object">byte</span>&#91;&#93; passwordHash = params.password.encodeAsMD5Bytes()</pre></div><p class="paragraph"/>
<strong class="bold">SHA1Codec</strong><p class="paragraph"/>Uses the SHA1 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a lowercase hexadecimal string. Example of usage:<p class="paragraph"/><div class="code"><pre>Your API Key: $&#123;user.uniqueID.encodeAsSHA1()&#125;</pre></div><p class="paragraph"/><strong class="bold">SHA1BytesCodec</strong><p class="paragraph"/>Uses the SHA1 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a byte array. Example of usage:<p class="paragraph"/><div class="code"><pre><span class="java&#45;object">byte</span>&#91;&#93; passwordHash = params.password.encodeAsSHA1Bytes()</pre></div><p class="paragraph"/>
<strong class="bold">SHA256Codec</strong><p class="paragraph"/>Uses the SHA256 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a lowercase hexadecimal string. Example of usage:<p class="paragraph"/><div class="code"><pre>Your API Key: $&#123;user.uniqueID.encodeAsSHA256()&#125;</pre></div><p class="paragraph"/><strong class="bold">SHA256BytesCodec</strong><p class="paragraph"/>Uses the SHA256 algorithm to digest byte arrays or lists of integers, or the bytes of a string (in default system encoding), as a byte array. Example of usage:<p class="paragraph"/><div class="code"><pre><span class="java&#45;object">byte</span>&#91;&#93; passwordHash = params.password.encodeAsSHA256Bytes()</pre></div><p class="paragraph"/>
<h4>Custom Codecs</h4><p class="paragraph"/>Applications may define their own codecs and Grails will load them along with the standard codecs. A custom codec class must be defined in the <code>grails-app/utils/</code> directory and the class name must end with <code>Codec</code>. The codec may contain a <code>static</code> <code>encode</code> closure, a <code>static</code> <code>decode</code> closure or both. The closure must accept a single argument which will be the object that the dynamic method was invoked on. For Example:<p class="paragraph"/><div class="code"><pre>class PigLatinCodec &#123;
<span class="java&#45;keyword">static</span> encode = &#123; str &#45;&#62;
// convert the string to pig latin and <span class="java&#45;keyword">return</span> the result
&#125;
&#125;</pre></div><p class="paragraph"/>
With the above codec in place an application could do something like this:<p class="paragraph"/><div class="code"><pre>$&#123;lastName.encodeAsPigLatin()&#125;</pre></div><p class="paragraph"/>
<h2 id="11.3 Authentication">11.3 Authentication</h2>
Grails has no default mechanism for authentication as it is possible to implement authentication in many different ways. It is however, easy to implement a simple authentication mechanism using either <a href="../guide/single.html#6.1.5%20Controller%20Interceptors" class="guide">interceptors</a> or <a href="../guide/single.html#6.6%20Filters" class="guide">filters</a>. This is sufficient for simple use cases but it's highly preferable to use an established security framework, for example by using the <a href="../guide/single.html#11.4.1%20Spring%20Security" class="guide">Spring Security</a> or the <a href="../guide/single.html#11.4.2%20Shiro" class="guide">Shiro</a> plugin.<p class="paragraph"/>Filters let you apply authentication across all controllers or across a URI space. For example you can create a new set of filters in a class called <code>grails-app/conf/SecurityFilters.groovy</code> by running:<p class="paragraph"/><div class="code"><pre>grails create&#45;filters security</pre></div><p class="paragraph"/>and implement your interception logic there:<p class="paragraph"/><div class="code"><pre>class SecurityFilters &#123;
def filters = &#123;
loginCheck(controller: '&#42;', action: '&#42;') &#123;
before = &#123;
<span class="java&#45;keyword">if</span> (!session.user &#38;&#38; actionName != <span class="java&#45;quote">"login"</span>) &#123;
redirect(controller: <span class="java&#45;quote">"user"</span>, action: <span class="java&#45;quote">"login"</span>)
<span class="java&#45;keyword">return</span> <span class="java&#45;keyword">false</span>
&#125;
&#125;
&#125;
&#125;
&#125;</pre></div><p class="paragraph"/>Here the <code>loginCheck</code> filter intercepts execution <em class="italic">before</em> all actions except <code>login</code> are executed, and if there is no user in the session then redirect to the <code>login</code> action.<p class="paragraph"/>The <code>login</code> action itself is trivial too:<p class="paragraph"/><div class="code"><pre>def login() &#123;
<span class="java&#45;keyword">if</span> (request.get) &#123;
<span class="java&#45;keyword">return</span> // render the login view
&#125;<p class="paragraph"/> def u = User.findByLogin(params.login)
<span class="java&#45;keyword">if</span> (u) &#123;
<span class="java&#45;keyword">if</span> (u.password == params.password) &#123;
session.user = u
redirect(action: <span class="java&#45;quote">"home"</span>)
&#125;
<span class="java&#45;keyword">else</span> &#123;
render(view: <span class="java&#45;quote">"login"</span>, model: &#91;message: <span class="java&#45;quote">"Password incorrect"</span>&#93;)
&#125;
&#125;
<span class="java&#45;keyword">else</span> &#123;
render(view: <span class="java&#45;quote">"login"</span>, model: &#91;message: <span class="java&#45;quote">"User not found"</span>&#93;)
&#125;
&#125;</pre></div>
<h2 id="11.4 Security Plug-ins">11.4 Security Plug-ins</h2>
If you need more advanced functionality beyond simple authentication such as authorization, roles etc. then you may want to consider using one of the available security plug-ins.
<h2 id="11.4.1 Spring Security">11.4.1 Spring Security</h2>
The Spring Security plugins are built on the <a href="http://static.springsource.org/spring-security/site/" target="blank">Spring Security</a> project which provides a flexible, extensible framework for building all sorts of authentication and authorization schemes. The plugins are modular so you can install just the functionality that you need for your application. The Spring Security plugins are the official security plugins for Grails and are actively maintained and supported.<p class="paragraph"/>There is a <a href="http://grails.org/plugin/spring-security-core" target="blank">Core plugin</a> which supports form-based authentication, encrypted/salted passwords, HTTP Basic authentication, etc. and secondary dependent plugins provide alternate functionality such as <a href="http://grails.org/plugin/spring-security-openid" target="blank">OpenID authentication</a>, <a href="http://grails.org/plugin/spring-security-acl" target="blank">ACL support</a>, <a href="http://grails.org/plugin/spring-security-cas" target="blank">single sign-on with Jasig CAS</a>, <a href="http://grails.org/plugin/spring-security-ldap" target="blank">LDAP authentication</a>, <a href="http://grails.org/plugin/spring-security-kerberos" target="blank">Kerberos authentication</a>, and a plugin providing <a href="http://grails.org/plugin/spring-security-ui" target="blank">user interface extensions</a> and security workflows.<p class="paragraph"/>See the <a href="http://grails.org/plugin/spring-security-core" target="blank">Core plugin page</a> for basic information and the <a href="http://burtbeckwith.github.com/grails-spring-security-core/" target="blank">user guide</a> for detailed information.
<h2 id="11.4.2 Shiro">11.4.2 Shiro</h2>
<a href="http://incubator.apache.org/shiro/" target="blank">Shiro</a> is a Java POJO oriented security framework that provides a default domain model that models realms, users, roles and permissions. With Shiro you have to extends a controller base called called <code>JsecAuthBase</code> in each controller you want secured and then provide an <code>accessControl</code> block to setup the roles. An example below:<p class="paragraph"/><div class="code"><pre>class ExampleController <span class="java&#45;keyword">extends</span> JsecAuthBase &#123;
<span class="java&#45;keyword">static</span> accessControl = &#123;
// All actions require the 'Observer' role.
role(name: 'Observer')<p class="paragraph"/> // The 'edit' action requires the 'Administrator' role.
role(name: 'Administrator', action: 'edit')<p class="paragraph"/> // Alternatively, several actions can be specified.
role(name: 'Administrator', only: &#91; 'create', 'edit', 'save', 'update' &#93;)
&#125;<p class="paragraph"/> &#8230;
&#125;</pre></div><p class="paragraph"/>For more information on the Shiro plugin refer to the <a href="http://grails.org/plugin/shiro" target="blank">documentation</a>.
<div style="clear:both;margin-top:15px;"></div>
<div class="toc-item prev-left"><a href="../guide/10.%20Internationalization.html">&lt;&lt; <strong>10</strong><span>Internationalization</span></a></div>
<div class="toc-item next-right"><a href="../guide/12.%20Plug-ins.html"><strong>12</strong><span>Plug-ins</span> >></a></div>
<div style="clear:both"></div>
</div>
</td>
<td id="col2">
<div class="local clearfix">
<div class="local-title">
<a href="../guide/index.html" target="mainFrame">Quick Reference</a>
<span class="toggle">(<a href="#" onclick="localToggle(); return false;">hide</a>)</span>
</div>
<div class="menu">
<div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Command Line</h1><div class="menu-sub">
<div class="menu-item"><a href="../ref/Command%20Line/Usage.html">Usage</a></div>
<div class="menu-item"><a href="../ref/Command%20Line/add-proxy.html">add-proxy</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/bootstrap.html">bootstrap</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/bug-report.html">bug-report</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/clean.html">clean</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/clear-proxy.html">clear-proxy</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/compile.html">compile</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/console.html">console</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/create-app.html">create-app</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/create-controller.html">create-controller</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/create-domain-class.html">create-domain-class</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/create-filters.html">create-filters</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/create-hibernate-cfg-xml.html">create-hibernate-cfg-xml</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/create-integration-test.html">create-integration-test</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/create-plugin.html">create-plugin</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/create-script.html">create-script</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/create-service.html">create-service</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/create-tag-lib.html">create-tag-lib</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/create-unit-test.html">create-unit-test</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/dependency-report.html">dependency-report</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/doc.html">doc</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/generate-all.html">generate-all</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/generate-controller.html">generate-controller</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/generate-views.html">generate-views</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/help.html">help</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/init.html">init</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/install-dependency.html">install-dependency</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/install-plugin.html">install-plugin</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/install-templates.html">install-templates</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/integrate-with.html">integrate-with</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/interactive.html">interactive</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/list-plugin-updates.html">list-plugin-updates</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/list-plugins.html">list-plugins</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/package-plugin.html">package-plugin</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/package.html">package</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/plugin-info.html">plugin-info</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/release-plugin.html">release-plugin</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/remove-proxy.html">remove-proxy</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/run-app.html">run-app</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/run-script.html">run-script</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/run-war.html">run-war</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/schema-export.html">schema-export</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/set-proxy.html">set-proxy</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/set-version.html">set-version</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/shell.html">shell</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/stats.html">stats</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/test-app.html">test-app</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/uninstall-plugin.html">uninstall-plugin</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/upgrade.html">upgrade</a>
</div>
<div class="menu-item"><a href="../ref/Command%20Line/war.html">war</a>
</div>
</div>
</div>
<div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Constraints</h1><div class="menu-sub">
<div class="menu-item"><a href="../ref/Constraints/Usage.html">Usage</a></div>
<div class="menu-item"><a href="../ref/Constraints/attributes.html">attributes</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/blank.html">blank</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/creditCard.html">creditCard</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/email.html">email</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/inList.html">inList</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/matches.html">matches</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/max.html">max</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/maxSize.html">maxSize</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/min.html">min</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/minSize.html">minSize</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/notEqual.html">notEqual</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/nullable.html">nullable</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/range.html">range</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/scale.html">scale</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/size.html">size</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/unique.html">unique</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/url.html">url</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/validator.html">validator</a>
</div>
<div class="menu-item"><a href="../ref/Constraints/widget.html">widget</a>
</div>
</div>
</div>
<div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Controllers</h1><div class="menu-sub">
<div class="menu-item"><a href="../ref/Controllers/Usage.html">Usage</a></div>
<div class="menu-item"><a href="../ref/Controllers/actionName.html">actionName</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/afterInterceptor.html">afterInterceptor</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/allowedMethods.html">allowedMethods</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/beforeInterceptor.html">beforeInterceptor</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/bindData.html">bindData</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/chain.html">chain</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/controllerName.html">controllerName</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/defaultAction.html">defaultAction</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/flash.html">flash</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/forward.html">forward</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/grailsApplication.html">grailsApplication</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/params.html">params</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/redirect.html">redirect</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/render.html">render</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/request.html">request</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/response.html">response</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/servletContext.html">servletContext</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/session.html">session</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/withForm.html">withForm</a>
</div>
<div class="menu-item"><a href="../ref/Controllers/withFormat.html">withFormat</a>
</div>
</div>
</div>
<div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Database Mapping</h1><div class="menu-sub">
<div class="menu-item"><a href="../ref/Database%20Mapping/Usage.html">Usage</a></div>
<div class="menu-item"><a href="../ref/Database%20Mapping/autoImport.html">autoImport</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/autoTimestamp.html">autoTimestamp</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/batchSize.html">batchSize</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/cache.html">cache</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/cascade.html">cascade</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/column.html">column</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/discriminator.html">discriminator</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/dynamicInsert.html">dynamicInsert</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/dynamicUpdate.html">dynamicUpdate</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/fetch.html">fetch</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/id.html">id</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/ignoreNotFound.html">ignoreNotFound</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/indexColumn.html">indexColumn</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/insertable.html">insertable</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/joinTable.html">joinTable</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/lazy.html">lazy</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/order.html">order</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/sort.html">sort</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/table.html">table</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/type.html">type</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/updateable.html">updateable</a>
</div>
<div class="menu-item"><a href="../ref/Database%20Mapping/version.html">version</a>
</div>
</div>
</div>
<div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Domain Classes</h1><div class="menu-sub">
<div class="menu-item"><a href="../ref/Domain%20Classes/Usage.html">Usage</a></div>
<div class="menu-item"><a href="../ref/Domain%20Classes/addTo.html">addTo</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/attach.html">attach</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/belongsTo.html">belongsTo</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/clearErrors.html">clearErrors</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/constraints.html">constraints</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/count.html">count</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/countBy.html">countBy</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/createCriteria.html">createCriteria</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/delete.html">delete</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/discard.html">discard</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/embedded.html">embedded</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/errors.html">errors</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/executeQuery.html">executeQuery</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/executeUpdate.html">executeUpdate</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/exists.html">exists</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/fetchMode.html">fetchMode</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/find.html">find</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/findAll.html">findAll</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/findAllBy.html">findAllBy</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/findAllWhere.html">findAllWhere</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/findBy.html">findBy</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/findWhere.html">findWhere</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/get.html">get</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/getAll.html">getAll</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/getDirtyPropertyNames.html">getDirtyPropertyNames</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/getPersistentValue.html">getPersistentValue</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/hasErrors.html">hasErrors</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/hasMany.html">hasMany</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/hasOne.html">hasOne</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/ident.html">ident</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/instanceOf.html">instanceOf</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/isAttached.html">isAttached</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/isDirty.html">isDirty</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/list.html">list</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/listOrderBy.html">listOrderBy</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/load.html">load</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/lock.html">lock</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/mappedBy.html">mappedBy</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/mapping.html">mapping</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/merge.html">merge</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/namedQueries.html">namedQueries</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/properties.html">properties</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/read.html">read</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/refresh.html">refresh</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/removeFrom.html">removeFrom</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/save.html">save</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/transients.html">transients</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/validate.html">validate</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/withCriteria.html">withCriteria</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/withNewSession.html">withNewSession</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/withSession.html">withSession</a>
</div>
<div class="menu-item"><a href="../ref/Domain%20Classes/withTransaction.html">withTransaction</a>
</div>
</div>
</div>
<div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Plug-ins</h1><div class="menu-sub">
<div class="menu-item"><a href="../ref/Plug-ins/Usage.html">Usage</a></div>
<div class="menu-item"><a href="../ref/Plug-ins/URL%20mappings.html">URL mappings</a>
</div>
<div class="menu-item"><a href="../ref/Plug-ins/codecs.html">codecs</a>
</div>
<div class="menu-item"><a href="../ref/Plug-ins/controllers.html">controllers</a>
</div>
<div class="menu-item"><a href="../ref/Plug-ins/core.html">core</a>
</div>
<div class="menu-item"><a href="../ref/Plug-ins/dataSource.html">dataSource</a>
</div>
<div class="menu-item"><a href="../ref/Plug-ins/domainClasses.html">domainClasses</a>
</div>
<div class="menu-item"><a href="../ref/Plug-ins/filters.html">filters</a>
</div>
<div class="menu-item"><a href="../ref/Plug-ins/hibernate.html">hibernate</a>
</div>
<div class="menu-item"><a href="../ref/Plug-ins/i18n.html">i18n</a>
</div>
<div class="menu-item"><a href="../ref/Plug-ins/logging.html">logging</a>
</div>
<div class="menu-item"><a href="../ref/Plug-ins/scaffolding.html">scaffolding</a>
</div>
<div class="menu-item"><a href="../ref/Plug-ins/services.html">services</a>
</div>
<div class="menu-item"><a href="../ref/Plug-ins/servlets.html">servlets</a>
</div>
<div class="menu-item"><a href="../ref/Plug-ins/web%20flow.html">web flow</a>
</div>
</div>
</div>
<div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Services</h1><div class="menu-sub">
<div class="menu-item"><a href="../ref/Services/Usage.html">Usage</a></div>
<div class="menu-item"><a href="../ref/Services/scope.html">scope</a>
</div>
<div class="menu-item"><a href="../ref/Services/transactional.html">transactional</a>
</div>
</div>
</div>
<div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Servlet API</h1><div class="menu-sub">
<div class="menu-item"><a href="../ref/Servlet%20API/request.html">request</a>
</div>
<div class="menu-item"><a href="../ref/Servlet%20API/response.html">response</a>
</div>
<div class="menu-item"><a href="../ref/Servlet%20API/servletContext.html">servletContext</a>
</div>
<div class="menu-item"><a href="../ref/Servlet%20API/session.html">session</a>
</div>
</div>
</div>
<div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Tag Libraries</h1><div class="menu-sub">
<div class="menu-item"><a href="../ref/Tag%20Libraries/Usage.html">Usage</a></div>
<div class="menu-item"><a href="../ref/Tag%20Libraries/actionName.html">actionName</a>
</div>
<div class="menu-item"><a href="../ref/Tag%20Libraries/controllerName.html">controllerName</a>
</div>
<div class="menu-item"><a href="../ref/Tag%20Libraries/flash.html">flash</a>
</div>
<div class="menu-item"><a href="../ref/Tag%20Libraries/pageScope.html">pageScope</a>
</div>
<div class="menu-item"><a href="../ref/Tag%20Libraries/params.html">params</a>
</div>
<div class="menu-item"><a href="../ref/Tag%20Libraries/request.html">request</a>
</div>
<div class="menu-item"><a href="../ref/Tag%20Libraries/response.html">response</a>
</div>
<div class="menu-item"><a href="../ref/Tag%20Libraries/servletContext.html">servletContext</a>
</div>
<div class="menu-item"><a href="../ref/Tag%20Libraries/session.html">session</a>
</div>
</div>
</div>
<div class="menu-block"><h1 class="menu-title" onclick="toggleRef(this.parentNode.childNodes[1])">Tags</h1><div class="menu-sub">
<div class="menu-item"><a href="../ref/Tags/actionSubmit.html">actionSubmit</a>
</div>
<div class="menu-item"><a href="../ref/Tags/actionSubmitImage.html">actionSubmitImage</a>
</div>
<div class="menu-item"><a href="../ref/Tags/applyLayout.html">applyLayout</a>
</div>
<div class="menu-item"><a href="../ref/Tags/checkBox.html">checkBox</a>
</div>
<div class="menu-item"><a href="../ref/Tags/collect.html">collect</a>
</div>
<div class="menu-item"><a href="../ref/Tags/cookie.html">cookie</a>
</div>
<div class="menu-item"><a href="../ref/Tags/country.html">country</a>
</div>
<div class="menu-item"><a href="../ref/Tags/countrySelect.html">countrySelect</a>
</div>
<div class="menu-item"><a href="../ref/Tags/createLink.html">createLink</a>
</div>
<div class="menu-item"><a href="../ref/Tags/createLinkTo.html">createLinkTo</a>
</div>
<div class="menu-item"><a href="../ref/Tags/currencySelect.html">currencySelect</a>
</div>
<div class="menu-item"><a href="../ref/Tags/datePicker.html">datePicker</a>
</div>
<div class="menu-item"><a href="../ref/Tags/each.html">each</a>
</div>
<div class="menu-item"><a href="../ref/Tags/eachError.html">eachError</a>
</div>
<div class="menu-item"><a href="../ref/Tags/else.html">else</a>
</div>
<div class="menu-item"><a href="../ref/Tags/elseif.html">elseif</a>
</div>
<div class="menu-item"><a href="../ref/Tags/fieldValue.html">fieldValue</a>
</div>
<div class="menu-item"><a href="../ref/Tags/findAll.html">findAll</a>
</div>
<div class="menu-item"><a href="../ref/Tags/form.html">form</a>
</div>
<div class="menu-item"><a href="../ref/Tags/formRemote.html">formRemote</a>
</div>
<div class="menu-item"><a href="../ref/Tags/formatBoolean.html">formatBoolean</a>
</div>
<div class="menu-item"><a href="../ref/Tags/formatDate.html">formatDate</a>
</div>
<div class="menu-item"><a href="../ref/Tags/formatNumber.html">formatNumber</a>
</div>
<div class="menu-item"><a href="../ref/Tags/grep.html">grep</a>
</div>
<div class="menu-item"><a href="../ref/Tags/hasErrors.html">hasErrors</a>
</div>
<div class="menu-item"><a href="../ref/Tags/header.html">header</a>
</div>
<div class="menu-item"><a href="../ref/Tags/hiddenField.html">hiddenField</a>
</div>
<div class="menu-item"><a href="../ref/Tags/if.html">if</a>
</div>
<div class="menu-item"><a href="../ref/Tags/include.html">include</a>
</div>
<div class="menu-item"><a href="../ref/Tags/javascript.html">javascript</a>
</div>
<div class="menu-item"><a href="../ref/Tags/join.html">join</a>
</div>
<div class="menu-item"><a href="../ref/Tags/layoutBody.html">layoutBody</a>
</div>
<div class="menu-item"><a href="../ref/Tags/layoutHead.html">layoutHead</a>
</div>
<div class="menu-item"><a href="../ref/Tags/layoutTitle.html">layoutTitle</a>
</div>
<div class="menu-item"><a href="../ref/Tags/link.html">link</a>
</div>
<div class="menu-item"><a href="../ref/Tags/localeSelect.html">localeSelect</a>
</div>
<div class="menu-item"><a href="../ref/Tags/message.html">message</a>
</div>
<div class="menu-item"><a href="../ref/Tags/meta.html">meta</a>
</div>
<div class="menu-item"><a href="../ref/Tags/pageProperty.html">pageProperty</a>
</div>
<div class="menu-item"><a href="../ref/Tags/paginate.html">paginate</a>
</div>
<div class="menu-item"><a href="../ref/Tags/passwordField.html">passwordField</a>
</div>
<div class="menu-item"><a href="../ref/Tags/radio.html">radio</a>
</div>
<div class="menu-item"><a href="../ref/Tags/radioGroup.html">radioGroup</a>
</div>
<div class="menu-item"><a href="../ref/Tags/remoteField.html">remoteField</a>
</div>
<div class="menu-item"><a href="../ref/Tags/remoteFunction.html">remoteFunction</a>
</div>
<div class="menu-item"><a href="../ref/Tags/remoteLink.html">remoteLink</a>
</div>
<div class="menu-item"><a href="../ref/Tags/render.html">render</a>
</div>
<div class="menu-item"><a href="../ref/Tags/renderErrors.html">renderErrors</a>
</div>
<div class="menu-item"><a href="../ref/Tags/resource.html">resource</a>
</div>
<div class="menu-item"><a href="../ref/Tags/select.html">select</a>
</div>
<div class="menu-item"><a href="../ref/Tags/set.html">set</a>
</div>
<div class="menu-item"><a href="../ref/Tags/sortableColumn.html">sortableColumn</a>
</div>
<div class="menu-item"><a href="../ref/Tags/submitButton.html">submitButton</a>
</div>
<div class="menu-item"><a href="../ref/Tags/submitToRemote.html">submitToRemote</a>
</div>
<div class="menu-item"><a href="../ref/Tags/textArea.html">textArea</a>
</div>
<div class="menu-item"><a href="../ref/Tags/textField.html">textField</a>
</div>
<div class="menu-item"><a href="../ref/Tags/timeZoneSelect.html">timeZoneSelect</a>
</div>
<div class="menu-item"><a href="../ref/Tags/unless.html">unless</a>
</div>
<div class="menu-item"><a href="../ref/Tags/uploadForm.html">uploadForm</a>
</div>
<div class="menu-item"><a href="../ref/Tags/while.html">while</a>
</div>
</div>
</div>
</div>
</div>
</td>
</tr>
</table>
<div id="footer">
Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
Sponsored by <a href="http://springsource.com">SpringSource</a>
</div>
<script type="text/javascript" src="../js/docs.js"></script>
</body>
</html>