You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shiro.apache.org by lh...@apache.org on 2013/12/20 01:41:03 UTC

svn commit: r1552463 - in /shiro/site: publish/documentation.html publish/webapp-tutorial.html trunk/documentation.html trunk/webapp-tutorial.md

Author: lhazlewood
Date: Fri Dec 20 00:41:03 2013
New Revision: 1552463

URL: http://svn.apache.org/r1552463
Log:
Updated webapp tutorial to reflect permissions

Modified:
    shiro/site/publish/documentation.html
    shiro/site/publish/webapp-tutorial.html
    shiro/site/trunk/documentation.html
    shiro/site/trunk/webapp-tutorial.md

Modified: shiro/site/publish/documentation.html
URL: http://svn.apache.org/viewvc/shiro/site/publish/documentation.html?rev=1552463&r1=1552462&r2=1552463&view=diff
==============================================================================
--- shiro/site/publish/documentation.html (original)
+++ shiro/site/publish/documentation.html Fri Dec 20 00:41:03 2013
@@ -88,7 +88,7 @@
         with Apache Shiro</a> - full intro article on InfoQ.com
     </li>
     <li><a href="10-minute-tutorial.html" title="10 Minute Tutorial">10 Minute Tutorial</a></li>
-    <li><a href="webapp-tutorial.html" title="Begineer's Webapp Tutorial">Beginner's Webapp Tutorial: a step-by-step tutorial to enable Shiro in a web application</a></li>
+    <li><a href="webapp-tutorial.html" title="Beginner's Webapp Tutorial">Beginner's Webapp Tutorial: a step-by-step tutorial to enable Shiro in a web application</a></li>
 </ul>
 
 <h2><a name="Documentation-ApacheShiroReferenceandAPI"></a>Apache Shiro Reference and API</h2>

Modified: shiro/site/publish/webapp-tutorial.html
URL: http://svn.apache.org/viewvc/shiro/site/publish/webapp-tutorial.html?rev=1552463&r1=1552462&r2=1552463&view=diff
==============================================================================
--- shiro/site/publish/webapp-tutorial.html (original)
+++ shiro/site/publish/webapp-tutorial.html Fri Dec 20 00:41:03 2013
@@ -83,13 +83,24 @@
 <ul>
   <li><a href="http://www.infoq.com/articles/apache-shiro">Application Security with Apache Shiro</a></li>
   <li><a href="http://shiro.apache.org/10-minute-tutorial.html">Apache Shiro 10 Minute Tutorial</a></li>
-</ul><p>This step-by-step tutorial should take ~ 45 minutes to 1 hour to complete. When you are finished, you will have a very good idea of how Shiro works in a web application.</p><h2>Overview</h2><p>While Apache Shiro&rsquo;s core design goals allow it to be used to secure <em>any</em> JVM-based application, such as command line applications, server daemons, web apps, etc, this guide will focus on the most common use case: securing a web application running in a <a href="http://en.wikipedia.org/wiki/Java_Servlet">Servlet</a> container, such as Tomcat or Jetty.</p><h3>Prerequisites</h3><p>The following tools are expected to be installed on your local development machine in order to follow along with this tutorial.</p>
+</ul><p>This step-by-step tutorial should take ~ 45 minutes to 1 hour to complete. When you are finished, you will have a very good idea of how Shiro works in a web application.</p><h3>Table of Contents</h3>
+<ul>
+  <li><a href="#overview">Overview</a></li>
+  <li><a href="#project-setup">Project Setup</a></li>
+  <li><a href="#step1">Step 1: Enable Shiro</a></li>
+  <li><a href="#step2">Step 2: Connect to a User Store</a></li>
+  <li><a href="#step3">Step 3: Enable Login and Logout</a></li>
+  <li><a href="#step4">Step 4: User-Specific UI Changes</a></li>
+  <li><a href="#step5">Step 5: Allow Access to Only Authenticated Users</a></li>
+  <li><a href="#step6">Step 6: Role-based Access Control</a></li>
+  <li><a href="#step7">Step 7: Permission-based Access Control</a></li>
+</ul><p><a id="overview"></a></p><h2>Overview</h2><p>While Apache Shiro&rsquo;s core design goals allow it to be used to secure <em>any</em> JVM-based application, such as command line applications, server daemons, web apps, etc, this guide will focus on the most common use case: securing a web application running in a <a href="http://en.wikipedia.org/wiki/Java_Servlet">Servlet</a> container, such as Tomcat or Jetty.</p><h3>Prerequisites</h3><p>The following tools are expected to be installed on your local development machine in order to follow along with this tutorial.</p>
 <ul>
   <li>Git (tested w/ 1.7)</li>
   <li>Java SDK 7</li>
   <li>Maven 3</li>
   <li>Your favorite IDE, like IntelliJ IDEA or Eclipse, or even a simple text editor to view files and make changes.</li>
-</ul><h3>Tutorial Format</h3><p>This is a step-by-step tutorial. The tutorial, and all of its steps, exist as a Git repository. When you clone the git repository, the <code>master</code> branch is your starting point. Each step in the tutorial is a separate branch. You can follow along simply by checking out the git branch that reflects the tutorial step you are reviewing.</p><h3>The Application</h3><p>The web application we will build is a super webapp that can be used as a starting point for your own application. It will demonstrate user login, logout, user-specific welcome messages, access control to certain parts of the web application, and integration with a plugglable security data store.</p><p>We will start by setting up the project, including the build tool and declaring dependencies, as well as configuring the servlet <code>web.xml</code> file to launch the web application and the Shiro environment.</p><p>Once we complete setup, we will then layer in individual pieces of fu
 nctionality, including integration with a security data store, then enabling user login, logout, and access control.</p><h2>Project Setup</h2><p>Instead of having to manually set up a directory structure and initial set of basic files, we&rsquo;ve done this for you in a git repository.</p><h3>1. Fork the tutorial project</h3><p>On GitHub, visit the <a href="https://github.com/lhazlewood/apache-shiro-tutorial-webapp">tutorial project</a> and click the <code>Fork</code> button on the upper right.</p><h3>2. Clone your tutorial repository</h3><p>Now that you have forked the repository to your own GitHub account, clone it on your local machine:</p>
+</ul><h3>Tutorial Format</h3><p>This is a step-by-step tutorial. The tutorial, and all of its steps, exist as a Git repository. When you clone the git repository, the <code>master</code> branch is your starting point. Each step in the tutorial is a separate branch. You can follow along simply by checking out the git branch that reflects the tutorial step you are reviewing.</p><h3>The Application</h3><p>The web application we will build is a super webapp that can be used as a starting point for your own application. It will demonstrate user login, logout, user-specific welcome messages, access control to certain parts of the web application, and integration with a plugglable security data store.</p><p>We will start by setting up the project, including the build tool and declaring dependencies, as well as configuring the servlet <code>web.xml</code> file to launch the web application and the Shiro environment.</p><p>Once we complete setup, we will then layer in individual pieces of fu
 nctionality, including integration with a security data store, then enabling user login, logout, and access control.</p><p><a id="project-setup"></a></p><h2>Project Setup</h2><p>Instead of having to manually set up a directory structure and initial set of basic files, we&rsquo;ve done this for you in a git repository.</p><h3>1. Fork the tutorial project</h3><p>On GitHub, visit the <a href="https://github.com/lhazlewood/apache-shiro-tutorial-webapp">tutorial project</a> and click the <code>Fork</code> button on the upper right.</p><h3>2. Clone your tutorial repository</h3><p>Now that you have forked the repository to your own GitHub account, clone it on your local machine:</p>
 <pre><code>$ git clone git@github.com:$YOUR_GITHUB_USERNAME/apache-shiro-tutorial-webapp.git    
 </code></pre><p>(where <code>$YOUR_GITHUB_USERNAME</code> is your own GitHub username of course)</p><p>You can now <code>cd</code> into the cloned directory and see the project structure:</p>
 <pre><code>$ cd apache-shiro-tutorial-webapp
@@ -124,7 +135,7 @@
   <li><code>src/main/webapp/index.jsp</code>: the default site index page - this merely forwards the request on to our <code>home.jsp</code> homepage.</li>
 </ul><h3>4. Run the webapp</h3><p>Now that you&rsquo;ve cloned the project, you can run the web application by executing the following on the command line:</p>
 <pre><code>$ mvn jetty:run 
-</code></pre><p>Next, open your web browser to <a href="http://localhost:8080">localhost:8080</a>, and you&rsquo;ll see the home page with a <strong>Hello, World!</strong> greeting. </p><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><h2>Step 1: Enable Shiro</h2><p>Our initial repository <code>master</code> branch is just a simple generic web application that could be used as a template for any application. Let&rsquo;s add the bare minimum to enable Shiro in the web app next.</p><p>Perform the following git checkout command to load the <code>step1</code> branch:</p>
+</code></pre><p>Next, open your web browser to <a href="http://localhost:8080">localhost:8080</a>, and you&rsquo;ll see the home page with a <strong>Hello, World!</strong> greeting. </p><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><p><a id="step1"></a></p><h2>Step 1: Enable Shiro</h2><p>Our initial repository <code>master</code> branch is just a simple generic web application that could be used as a template for any application. Let&rsquo;s add the bare minimum to enable Shiro in the web app next.</p><p>Perform the following git checkout command to load the <code>step1</code> branch:</p>
 <pre><code>$ git checkout step1
 </code></pre><p>Checking out this branch, you will find two changes:</p>
 <ol>
@@ -172,7 +183,7 @@ securityManager.cacheManager = $cacheMan
 </code></pre><p>This time, you will see log output similar to the following, indicating that Shiro is indeed running in your webapp:</p>
 <pre><code>16:04:19.807 [main] INFO  o.a.shiro.web.env.EnvironmentLoader - Starting Shiro environment initialization.
 16:04:19.904 [main] INFO  o.a.shiro.web.env.EnvironmentLoader - Shiro environment initialized in 95 ms.
-</code></pre><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><h2>Step 2: Connect to a User Store</h2><p>Perform the following git checkout command to load the <code>step2</code> branch:</p>
+</code></pre><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><p><a id="step2"></a></p><h2>Step 2: Connect to a User Store</h2><p>Perform the following git checkout command to load the <code>step2</code> branch:</p>
 <pre><code>$ git checkout step2
 </code></pre><p>Now we have Shiro integrated and running within a webapp. But we haven&rsquo;t actually told Shiro to do anything yet!</p><p>Before we can login, or logout, or perform role-based or permission-based access control, or anything else security related, we need users!</p><p>We will need to configure Shiro to access a <em>User Store</em> of some type, so it can look up users to perform login attempts, or check roles for security decisions, etc. There are many types of user stores that any application might need to access: maybe you store users in a MySQL database, maybe in MongoDB, maybe your company stores user accounts in LDAP or Active Directory, maybe you store them in a simple file, or some other proprietary data store.</p><p>Shiro does this via what it calls a <a href="http://shiro.apache.org/architecture.html"><code>Realm</code></a>. From Shiro&rsquo;s documentation: </p>
 <blockquote><p>Realms act as the ‘bridge’ or ‘connector’ between Shiro and your application’s security data. When it comes time to actually interact with security-related data like user accounts to perform authentication (login) and authorization (access control), Shiro looks up many of these things from one or more Realms configured for an application. </p><p>In this sense a Realm is essentially a security-specific <a href="http://en.wikipedia.org/wiki/Data_access_object">DAO</a>: it encapsulates connection details for data sources and makes the associated data available to Shiro as needed. When configuring Shiro, you must specify at least one Realm to use for authentication and/or authorization. The SecurityManager may be configured with multiple Realms, but at least one is required. </p><p>Shiro provides out-of-the-box Realms to connect to a number of security data sources (aka directories) such as LDAP, relational databases (JDBC), text configuration sou
 rces like INI and properties files, and more. You can plug-in your own Realm implementations to represent custom data sources if the default Realms do not meet your needs. </p>
@@ -254,6 +265,7 @@ stormpathClient.cacheManager = $cacheMan
 stormpathClient.apiKeyFileLocation = $HOME/.stormpath/apiKey.properties
 stormpathRealm = com.stormpath.shiro.realm.ApplicationRealm
 stormpathRealm.client = $stormpathClient
+
 # Find this URL in your Stormpath console for an application you create:
 # Applications -&gt; (choose application name) --&gt; Details --&gt; REST URL
 stormpathRealm.applicationRestUrl = https://api.stormpath.com/v1/applications/$STORMPATH_APPLICATION_ID
@@ -271,7 +283,7 @@ securityManager.realm = $stormpathRealm
 <pre><code>16:08:25.466 [main] INFO  o.a.shiro.web.env.EnvironmentLoader - Starting Shiro environment initialization.
 16:08:26.201 [main] INFO  o.a.s.c.IniSecurityManagerFactory - Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur.
 16:08:26.201 [main] INFO  o.a.shiro.web.env.EnvironmentLoader - Shiro environment initialized in 731 ms.
-</code></pre><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><h2>Step 3: Enable Login and Logout</h2><p>Now we have users, and we can add, remove and disable them easily in a UI. Now we can start enabling features like login/logout and access control in our application.</p><p>Perform the following git checkout command to load the <code>step3</code> branch:</p>
+</code></pre><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><p><a id="step3"></a></p><h2>Step 3: Enable Login and Logout</h2><p>Now we have users, and we can add, remove and disable them easily in a UI. Now we can start enabling features like login/logout and access control in our application.</p><p>Perform the following git checkout command to load the <code>step3</code> branch:</p>
 <pre><code>$ git checkout step3
 </code></pre><p>This checkout will load the following 2 additions:</p>
 <ul>
@@ -304,7 +316,7 @@ shiro.loginUrl = /login.jsp
   <li>There is a <code>rememberMe</code> checkbox whose &lsquo;checked&rsquo; state can be a &lsquo;truthy&rsquo; value (<code>true</code>, <code>t</code>, <code>1</code>, <code>enabled</code>, <code>y</code>, <code>yes</code>, or <code>on</code>).</li>
 </ol><p>Our login.jsp form just uses the default <code>username</code>, <code>password</code>, and <code>rememberMe</code> form field names. They naems are configurable if you wish to change them - see the <a href="http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/authc/FormAuthenticationFilter.html"><code>FormAuthenticationFilter</code> JavaDoc</a> for information.</p><h3>Step 3c: Run the webapp</h3><p>After making the changes as specified in Step 2b and 2c, go ahead and run the web app:</p>
 <pre><code>$ mvn jetty:run
-</code></pre><h3>Step 3d: Try to Login</h3><p>With your web browser, navigate to <a href="http://localhost:8080/login.jsp">localhost:8080/login.jsp</a> and you will see our new shiny login form.</p><p>Enter in a username and password of the account you created at the end of Step 2, and hit &lsquo;Login&rsquo;. If the login is successful, you will be directed to the home page! If the login fails, you will be shown the login page again.</p><p>Tip: If you want a successful login to redirect the user to a different page other than the home page (context path <code>/</code>), you can set the <code>authc.successUrl = /whatever</code> in the INI&rsquo;s <code>[main]</code> section.</p><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><h2>Step 4: User-specific UI changes</h2><p>It&rsquo;s usually a requirement to change a web user interface based on who the user is. We can do that easily because Shiro supports a JSP tag library to do things based on the
  currently logged-in Subject (user).</p><p>Perform the following git checkout command to load the <code>step4</code> branch:</p>
+</code></pre><h3>Step 3d: Try to Login</h3><p>With your web browser, navigate to <a href="http://localhost:8080/login.jsp">localhost:8080/login.jsp</a> and you will see our new shiny login form.</p><p>Enter in a username and password of the account you created at the end of Step 2, and hit &lsquo;Login&rsquo;. If the login is successful, you will be directed to the home page! If the login fails, you will be shown the login page again.</p><p>Tip: If you want a successful login to redirect the user to a different page other than the home page (context path <code>/</code>), you can set the <code>authc.successUrl = /whatever</code> in the INI&rsquo;s <code>[main]</code> section.</p><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><p><a id="step4"></a></p><h2>Step 4: User-specific UI changes</h2><p>It&rsquo;s usually a requirement to change a web user interface based on who the user is. We can do that easily because Shiro supports a JSP tag library 
 to do things based on the currently logged-in Subject (user).</p><p>Perform the following git checkout command to load the <code>step4</code> branch:</p>
 <pre><code>$ git checkout step4
 </code></pre><p>This step makes some additions to our <code>home.jsp</code> page:</p>
 <ul>
@@ -337,7 +349,7 @@ shiro.loginUrl = /login.jsp
 <pre><code>Hi jsmith! (Log out)
 </code></pre><p>Assuming &lsquo;jsmith&rsquo; is the username of the account logged in. &lsquo;Log out&rsquo; is a hyperlink to the &lsquo;/logout&rsquo; url handled by the Shiro <code>logout</code> filter.</p><p>As you can see, you can turn off or on entire page sections, features and UI components. In addition to <code>&lt;shiro:guest&gt;</code> and <code>&lt;shiro:user&gt;</code>, Shiro supports <a href="http://shiro.apache.org/web.html#Web-taglibrary">many other useful JSP tags</a> that you can use to customize the UI based on various things known about the current <code>Subject</code>.</p><h3>Step 4c: Run the webapp</h3><p>After checking out the <code>step4</code> branch, go ahead and run the web app:</p>
 <pre><code>$ mvn jetty:run
-</code></pre><p>Try visiting <a href="http://localhost:8080">localhost:8080</a> as a guest, and then login. After successful login, you will see the page content change to reflect that you&rsquo;re now a known user!</p><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><h2>Step 5: Allow Access to Only Authenticated Users</h2><p>While you can change page content based on Subject state, often times you will want to restrict entire sections of your webapp based on if someone has <strong>proven</strong> their identity (authenticated) during their current interaction with the web application.</p><p>This is especially important if a user-only section of a webapp shows sensitive information, like billing details or the ability to control other users.</p><p>Perform the following git checkout command to load the <code>step5</code> branch:</p>
+</code></pre><p>Try visiting <a href="http://localhost:8080">localhost:8080</a> as a guest, and then login. After successful login, you will see the page content change to reflect that you&rsquo;re now a known user!</p><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><p><a id="step5"></a></p><h2>Step 5: Allow Access to Only Authenticated Users</h2><p>While you can change page content based on Subject state, often times you will want to restrict entire sections of your webapp based on if someone has <strong>proven</strong> their identity (authenticated) during their current interaction with the web application.</p><p>This is especially important if a user-only section of a webapp shows sensitive information, like billing details or the ability to control other users.</p><p>Perform the following git checkout command to load the <code>step5</code> branch:</p>
 <pre><code>$ git checkout step5
 </code></pre><p>Step 5 introduces the following 3 changes:</p>
 <ol>
@@ -354,7 +366,7 @@ shiro.loginUrl = /login.jsp
     you will need to log-in first.&lt;/p&gt;&lt;/shiro:notAuthenticated&gt;
 </code></pre><p>The <code>&lt;shiro:authenticated&gt;</code> tag will only display the contents if the current Subject has already logged in (authenticated) during their current session. This is how the <code>Subject</code> knows they can go visit a new part of the website.</p><p>The <code>&lt;shiro:notAuthenticated&gt;</code> tag will only display the contents if the current Subject is not yet authenticated during their current session.</p><p>But did you notice that the <code>notAuthenticated</code> content still has a URL to the <code>/account</code> section? That&rsquo;s ok - our <code>authc</code> filter will handle the login-and-then-redirect flow as described above.</p><p>Fire up the webapp with the new changes and try it out!</p><h3>Step 5d: Run the webapp</h3><p>After checking out the <code>step5</code> branch, go ahead and run the web app:</p>
 <pre><code>$ mvn jetty:run
-</code></pre><p>Try visiting <a href="http://localhost:8080">localhost:8080</a>. Once there, click the new <code>/account</code> link and watch it redirect you to force you to log in. Once logged in, return to the home page and see the content change again now that you&rsquo;re authenticated. You can visit the account page and the home page as often as you want, until you log out. Nice!</p><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><h2>Step 6: Role-Based Access Control</h2><p>In addition to controlling access based on authentication, it is often a requirement to restrict access to certain parts of the application based on what role(s) are assigned to the current <code>Subject</code>.</p><p>Perform the following git checkout command to load the <code>step5</code> branch:</p>
+</code></pre><p>Try visiting <a href="http://localhost:8080">localhost:8080</a>. Once there, click the new <code>/account</code> link and watch it redirect you to force you to log in. Once logged in, return to the home page and see the content change again now that you&rsquo;re authenticated. You can visit the account page and the home page as often as you want, until you log out. Nice!</p><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><p><a id="step6"></a></p><h2>Step 6: Role-Based Access Control</h2><p>In addition to controlling access based on authentication, it is often a requirement to restrict access to certain parts of the application based on what role(s) are assigned to the current <code>Subject</code>.</p><p>Perform the following git checkout command to load the <code>step5</code> branch:</p>
 <pre><code>$ git checkout step6
 </code></pre><h3>Step 6a: Add Roles</h3><p>In order to perform Role-Based Access Control, we need Roles to exist.</p><p>The fastest way to do that in this tutorial is to populate some Groups within Stormpath (in Stormpath, a Stormpath Group can serve the same purpose of a Role).</p><p>To do this, log in to the UI and navigate as follows:</p><p><strong>Directories &gt; Apache Shiro Tutorial Webapp Directory &gt; Groups</strong></p><p>Add the following three groups:</p>
 <ul>
@@ -384,9 +396,40 @@ shiro.loginUrl = /login.jsp
 &lt;/p&gt;
 </code></pre><p>The <code>&lt;shiro:hasRole&gt;</code> tag will only display the contents if the current Subject has been assigned the specified role.</p><p>The <code>&lt;shiro:lacksRole&gt;</code> tag will only display the contents if the current Subject <strong>has not</strong> been assigned the specified role.</p><h3>Step 6c: RBAC filter chains</h3><p>An exercise left to the reader (not a defined step) is to create a new section of the website and restrict URL access to that section of the website based on what role is assigned to the current user.</p><p>Hint: Create a <a href="http://shiro.apache.org/web.html#Web-FilterChainDefinitions">filter chain definition</a> for that new part of the webapp using the <a href="http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/authz/RolesAuthorizationFilter.html"><code>roles</code> filter</a></p><h3>Step 6d: Run the webapp</h3><p>After checking out the <code>step6</code> branch, go ahead and run the web app:</p>
 <pre><code>$ mvn jetty:run
-</code></pre><p>Try visiting <a href="http://localhost:8080">localhost:8080</a> and log in with different user accounts that are assigned different roles and watch the home page&rsquo;s <strong>Roles</strong> section content change!</p><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><h2>Summary</h2><p>We hope you have found this introductory tutorial for Shiro-enabled webapps useful. In coming editions of this tutorial, we will cover:</p>
+</code></pre><p>Try visiting <a href="http://localhost:8080">localhost:8080</a> and log in with different user accounts that are assigned different roles and watch the home page&rsquo;s <strong>Roles</strong> section content change!</p><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><p><a id="step7"></a></p><h2>Step 7: Permission-Based Access Control</h2><p>Role-based access control is good for many use cases, but it suffers from one major problem: you can&rsquo;t add or delete roles at runtime. Role checks are hard-coded with role names, so if you changed the role names or role configuration, or add or remove roles, you have to go back and change your code!</p><p>Because of this, Shiro has a powerful marquis feature: built-in support for <em>permissions</em>. In Shiro, a permission is a raw statement of functionality, for example &lsquo;open a door&rsquo; &lsquo;create a blog entry&rsquo;, &lsquo;delete the <code>jsmith</code> user&rsquo;, et
 c. Permissions reflect your application&rsquo;s raw functionality, so you only need to change permission checks when you change your application&rsquo;s functionlity - not if you want to change your role or user model.</p><p>To demonstrate this, we will create some permissions and assign them to a user, and then customize our web UI based on a user&rsquo;s authorization (permissions).</p><h3>Step 7a: Add Permissions</h3><p>Shiro <code>Realm</code>s are read-only components: every data store models roles, groups, permissions, accounts, and their relationships differently, so Shiro doesn&rsquo;t have a &lsquo;write&rsquo; API to modify these resources. To modify the underlying the model objects, you just modify them directly via whatever API you desire. Your Shiro Realm then knows how to read this information and represent it in a format Shiro understands.</p><p>As such, since we&rsquo;re using Stormpath in this sample app, we&rsquo;ll assign permissions to an account and group in a S
 tormpath API-specific way.</p><p>Let&rsquo;s execute a cURL request to add some permissions to our previously created Jean-Luc Picard account. Using that account&rsquo;s <code>href</code> URL, we&rsquo;ll post some <code>apacheShiroPermissions</code> to the account via <a href="http://docs.stormpath.com/rest/product-guide/#custom-data">custom data</a>:</p>
+<pre><code>curl -X POST --user $YOUR_API_KEY_ID:$YOUR_API_KEY_SECRET \
+    -H &quot;Accept: application/json&quot; \
+    -H &quot;Content-Type: application/json&quot; \
+    -d &#39;{
+            &quot;apacheShiroPermissions&quot;: [
+                &quot;ship:NCC-1701-D:command&quot;,
+                &quot;user:jlpicard:edit&quot;
+            ]
+        }&#39; \
+&quot;https://api.stormpath.com/v1/accounts/$JLPICARD_ACCOUNT_ID/customData&quot;
+</code></pre><p>where <code>$JLPICARD_ACCOUNT_ID</code> matches the uid of the Jean-Luc Picard you created at the beginning of this tutorial.</p><p>This adds two permissions directly to the Stormpath Account:</p>
+<ul>
+  <li><code>ship:NCC-1701-D:command</code></li>
+  <li><code>user:jlpicard:edit</code></li>
+</ul><p>These use Shiro&rsquo;s <a href="http://shiro.apache.org/permissions.html">WildcardPermission</a> syntax. </p><p>The first basically means <em>the ability to &lsquo;command&rsquo; the &lsquo;ship&rsquo; with identifier &lsquo;NCC-1701-D&rsquo;</em>. This is an example of an <em>instance-level</em> permission: controlling access to a specific <em>instance</em> <code>NCC-1701-D</code> of a resource <code>ship</code>. The second is also an instance-level permission that states <em>the ability to <code>edit</code> the <code>user</code> with identifier <code>jlpicard</code></em>.</p><p>How permissions are stored in Stormpath, as well as how to customize storage and access options in Stormpath is out of scope for this document, but this is explained in the <a href="https://github.com/stormpath/stormpath-shiro/wiki#permissions">Shiro Stormpath plugin documentation</a>.</p><h3>Step 7b: Permission Tags</h3><p>Just as we have JSP tags for role checks, parallel tags exist for permissio
 n checks as well. We update the <code>/home.jsp</code> page to let the user know if they&rsquo;re allowed to do something or not based on the permissions that are assigned to them. These messages are added in a new <code>&lt;h2&gt;Permissions&lt;/h2&gt;</code> section of the home page:</p>
+<pre><code>&lt;h2&gt;Permissions&lt;/h2&gt;
+
+&lt;ul&gt;
+    &lt;li&gt;You may &lt;shiro:lacksPermission name=&quot;ship:NCC-1701-D:command&quot;&gt;&lt;b&gt;NOT&lt;/b&gt; &lt;/shiro:lacksPermission&gt; command the &lt;code&gt;NCC-1701-D&lt;/code&gt; Starship!&lt;/li&gt;
+    &lt;li&gt;You may &lt;shiro:lacksPermission name=&quot;user:${account.username}:edit&quot;&gt;&lt;b&gt;NOT&lt;/b&gt; &lt;/shiro:lacksPermission&gt; edit the ${account.username} user!&lt;/li&gt;
+&lt;/ul&gt;
+</code></pre><p>When you visit the home page the first time, before you log in, you will see the following output:</p>
+<pre><code>You may NOT command the NCC-1701-D Starship!
+You may NOT edit the user!
+</code></pre><p>But after you log in with your Jean-Luc Picard account, you will see this instead:</p>
+<pre><code>You may command the NCC-1701-D Starship!
+You may edit the user!
+</code></pre><p>You can see that Shiro resolved that the authenticated user had permissions, and the output was rendered in an appropriate way.</p><p>You can also use the <code>&lt;shiro:hasPermission&gt;</code> tag for affirmative permission checks.</p><p>Finally, we&rsquo;ll call to attention an extremely powerful feature with permission checks. Did you see how the second permission check used a <em>runtime</em> generated permission value?</p>
+<pre><code>&lt;shiro:lacksPermission name=&quot;user:${account.username}:edit&quot;&gt; ...
+</code></pre><p>The <code>${account.username}</code> value is interpreted at runtime and forms the final <code>user:aUsername:edit</code> value, and then the final String value is used for the permission check.</p><p>This is <em>extremely</em> powerful: you can perform permission checks based on who the current user is and <em>what is currently being interacted with</em>. These runtime-based instance-level permission checks are a foundational technique for developing highly customizable and secure applications.</p><h3>Step 7c: Run the webapp</h3><p>After checking out the <code>step7</code> branch, go ahead and run the web app:</p>
+<pre><code>$ mvn jetty:run
+</code></pre><p>Try visiting <a href="http://localhost:8080">localhost:8080</a> and log in and out of the UI with your Jean-Luc Picard account (and other accounts), and see the page output change based on what permissions are assigned (or not)!</p><p>Hit <code>ctl-C</code> (or <code>cmd-C</code> on a mac) to shut down the web app.</p><h2>Summary</h2><p>We hope you have found this introductory tutorial for Shiro-enabled webapps useful. In coming editions of this tutorial, we will cover:</p>
 <ul>
-  <li>Shiro&rsquo;s extremely powerful <a href="http://shiro.apache.org/permissions.html">permissions</a> and Permission-Based Access Control.</li>
   <li>Plugging in different user data stores, like an RDBMS or NoSQL data store.</li>
 </ul><h3>Fixes and Pull Requests</h3><p>Please send any fixes for errata as a <a href="https://help.github.com/articles/creating-a-pull-request">GitHub Pull Request</a> to the <code>https://github.com/lhazlewood/apache-shiro-tutorial-webapp</code> repository. We appreciate it!!!</p>
 

Modified: shiro/site/trunk/documentation.html
URL: http://svn.apache.org/viewvc/shiro/site/trunk/documentation.html?rev=1552463&r1=1552462&r2=1552463&view=diff
==============================================================================
--- shiro/site/trunk/documentation.html (original)
+++ shiro/site/trunk/documentation.html Fri Dec 20 00:41:03 2013
@@ -7,7 +7,7 @@
         with Apache Shiro</a> - full intro article on InfoQ.com
     </li>
     <li><a href="10-minute-tutorial.html" title="10 Minute Tutorial">10 Minute Tutorial</a></li>
-    <li><a href="webapp-tutorial.html" title="Begineer's Webapp Tutorial">Beginner's Webapp Tutorial: a step-by-step tutorial to enable Shiro in a web application</a></li>
+    <li><a href="webapp-tutorial.html" title="Beginner's Webapp Tutorial">Beginner's Webapp Tutorial: a step-by-step tutorial to enable Shiro in a web application</a></li>
 </ul>
 
 <h2><a name="Documentation-ApacheShiroReferenceandAPI"></a>Apache Shiro Reference and API</h2>

Modified: shiro/site/trunk/webapp-tutorial.md
URL: http://svn.apache.org/viewvc/shiro/site/trunk/webapp-tutorial.md?rev=1552463&r1=1552462&r2=1552463&view=diff
==============================================================================
--- shiro/site/trunk/webapp-tutorial.md (original)
+++ shiro/site/trunk/webapp-tutorial.md Fri Dec 20 00:41:03 2013
@@ -9,6 +9,19 @@ This document is an introductory step-by
 
 This step-by-step tutorial should take ~ 45 minutes to 1 hour to complete.  When you are finished, you will have a very good idea of how Shiro works in a web application.
 
+### Table of Contents
+
+* [Overview](#overview)
+* [Project Setup](#project-setup)
+* [Step 1: Enable Shiro](#step1)
+* [Step 2: Connect to a User Store](#step2)
+* [Step 3: Enable Login and Logout](#step3)
+* [Step 4: User-Specific UI Changes](#step4)
+* [Step 5: Allow Access to Only Authenticated Users](#step5)
+* [Step 6: Role-based Access Control](#step6)
+* [Step 7: Permission-based Access Control](#step7)
+
+<a id="overview"></a>
 ## Overview
 
 While Apache Shiro's core design goals allow it to be used to secure _any_ JVM-based application, such as command line applications, server daemons, web apps, etc, this guide will focus on the most common use case: securing a web application running in a [Servlet](http://en.wikipedia.org/wiki/Java_Servlet) container, such as Tomcat or Jetty.
@@ -34,6 +47,7 @@ We will start by setting up the project,
 
 Once we complete setup, we will then layer in individual pieces of functionality, including integration with a security data store, then enabling user login, logout, and access control.
 
+<a id="project-setup"></a>
 ## Project Setup
 
 Instead of having to manually set up a directory structure and initial set of basic files, we've done this for you in a git repository.
@@ -98,6 +112,7 @@ Next, open your web browser to [localhos
 
 Hit `ctl-C` (or `cmd-C` on a mac) to shut down the web app.
 
+<a id="step1"></a>
 ## Step 1: Enable Shiro
 
 Our initial repository `master` branch is just a simple generic web application that could be used as a template for any application.  Let's add the bare minimum to enable Shiro in the web app next.
@@ -177,6 +192,7 @@ This time, you will see log output simil
 
 Hit `ctl-C` (or `cmd-C` on a mac) to shut down the web app.
 
+<a id="step2"></a>
 ## Step 2: Connect to a User Store
 
 Perform the following git checkout command to load the `step2` branch:
@@ -316,6 +332,7 @@ If you've checked out the `step2` branch
     stormpathClient.apiKeyFileLocation = $HOME/.stormpath/apiKey.properties
     stormpathRealm = com.stormpath.shiro.realm.ApplicationRealm
     stormpathRealm.client = $stormpathClient
+    
     # Find this URL in your Stormpath console for an application you create:
     # Applications -> (choose application name) --> Details --> REST URL
     stormpathRealm.applicationRestUrl = https://api.stormpath.com/v1/applications/$STORMPATH_APPLICATION_ID
@@ -348,6 +365,7 @@ This time, you will see log output simil
 
 Hit `ctl-C` (or `cmd-C` on a mac) to shut down the web app.
 
+<a id="step3"></a>
 ## Step 3: Enable Login and Logout
 
 Now we have users, and we can add, remove and disable them easily in a UI.  Now we can start enabling features like login/logout and access control in our application.
@@ -432,6 +450,7 @@ Tip: If you want a successful login to r
 
 Hit `ctl-C` (or `cmd-C` on a mac) to shut down the web app.
 
+<a id="step4"></a>
 ## Step 4: User-specific UI changes
 
 It's usually a requirement to change a web user interface based on who the user is.  We can do that easily because Shiro supports a JSP tag library to do things based on the currently logged-in Subject (user).
@@ -503,6 +522,7 @@ Try visiting [localhost:8080](http://loc
 
 Hit `ctl-C` (or `cmd-C` on a mac) to shut down the web app.
 
+<a id="step5"></a>
 ## Step 5: Allow Access to Only Authenticated Users
 
 While you can change page content based on Subject state, often times you will want to restrict entire sections of your webapp based on if someone has **proven** their identity (authenticated) during their current interaction with the web application.
@@ -568,6 +588,7 @@ Try visiting [localhost:8080](http://loc
 
 Hit `ctl-C` (or `cmd-C` on a mac) to shut down the web app.
 
+<a id="step6"></a>
 ## Step 6: Role-Based Access Control
 
 In addition to controlling access based on authentication, it is often a requirement to restrict access to certain parts of the application based on what role(s) are assigned to the current `Subject`.
@@ -641,11 +662,94 @@ Try visiting [localhost:8080](http://loc
 
 Hit `ctl-C` (or `cmd-C` on a mac) to shut down the web app.
 
+<a id="step7"></a>
+## Step 7: Permission-Based Access Control
+
+Role-based access control is good for many use cases, but it suffers from one major problem: you can't add or delete roles at runtime.  Role checks are hard-coded with role names, so if you changed the role names or role configuration, or add or remove roles, you have to go back and change your code!
+
+Because of this, Shiro has a powerful marquis feature: built-in support for _permissions_.  In Shiro, a permission is a raw statement of functionality, for example 'open a door' 'create a blog entry', 'delete the `jsmith` user', etc.  Permissions reflect your application's raw functionality, so you only need to change permission checks when you change your application's functionlity - not if you want to change your role or user model.
+
+To demonstrate this, we will create some permissions and assign them to a user, and then customize our web UI based on a user's authorization (permissions).
+
+### Step 7a: Add Permissions
+
+Shiro `Realm`s are read-only components: every data store models roles, groups, permissions, accounts, and their relationships differently, so Shiro doesn't have a 'write' API to modify these resources.  To modify the underlying the model objects, you just modify them directly via whatever API you desire.  Your Shiro Realm then knows how to read this information and represent it in a format Shiro understands.
+
+As such, since we're using Stormpath in this sample app, we'll assign permissions to an account and group in a Stormpath API-specific way.
+
+Let's execute a cURL request to add some permissions to our previously created Jean-Luc Picard account.  Using that account's `href` URL, we'll post some `apacheShiroPermissions` to the account via [custom data](http://docs.stormpath.com/rest/product-guide/#custom-data):
+
+    curl -X POST --user $YOUR_API_KEY_ID:$YOUR_API_KEY_SECRET \
+        -H "Accept: application/json" \
+        -H "Content-Type: application/json" \
+        -d '{
+                "apacheShiroPermissions": [
+                    "ship:NCC-1701-D:command",
+                    "user:jlpicard:edit"
+                ]
+            }' \
+    "https://api.stormpath.com/v1/accounts/$JLPICARD_ACCOUNT_ID/customData"
+   
+where `$JLPICARD_ACCOUNT_ID` matches the uid of the Jean-Luc Picard you created at the beginning of this tutorial.
+
+This adds two permissions directly to the Stormpath Account:
+
+* `ship:NCC-1701-D:command`
+* `user:jlpicard:edit`
+
+These use Shiro's [WildcardPermission](http://shiro.apache.org/permissions.html) syntax.  
+
+The first basically means _the ability to 'command' the 'ship' with identifier 'NCC-1701-D'_.  This is an example of an _instance-level_ permission: controlling access to a specific _instance_ `NCC-1701-D` of a resource `ship`.  The second is also an instance-level permission that states _the ability to `edit` the `user` with identifier `jlpicard`_.
+
+How permissions are stored in Stormpath, as well as how to customize storage and access options in Stormpath is out of scope for this document, but this is explained in the [Shiro Stormpath plugin documentation](https://github.com/stormpath/stormpath-shiro/wiki#permissions).
+
+### Step 7b: Permission Tags
+
+Just as we have JSP tags for role checks, parallel tags exist for permission checks as well.  We update the `/home.jsp` page to let the user know if they're allowed to do something or not based on the permissions that are assigned to them.  These messages are added in a new `<h2>Permissions</h2>` section of the home page:
+
+    <h2>Permissions</h2>
+    
+    <ul>
+        <li>You may <shiro:lacksPermission name="ship:NCC-1701-D:command"><b>NOT</b> </shiro:lacksPermission> command the <code>NCC-1701-D</code> Starship!</li>
+        <li>You may <shiro:lacksPermission name="user:${account.username}:edit"><b>NOT</b> </shiro:lacksPermission> edit the ${account.username} user!</li>
+    </ul>
+
+When you visit the home page the first time, before you log in, you will see the following output:
+
+    You may NOT command the NCC-1701-D Starship!
+    You may NOT edit the user!
+
+But after you log in with your Jean-Luc Picard account, you will see this instead:
+
+    You may command the NCC-1701-D Starship!
+    You may edit the user!
+
+You can see that Shiro resolved that the authenticated user had permissions, and the output was rendered in an appropriate way.
+
+You can also use the `<shiro:hasPermission>` tag for affirmative permission checks.
+
+Finally, we'll call to attention an extremely powerful feature with permission checks.  Did you see how the second permission check used a _runtime_ generated permission value?
+
+    <shiro:lacksPermission name="user:${account.username}:edit"> ...
+
+The `${account.username}` value is interpreted at runtime and forms the final `user:aUsername:edit` value, and then the final String value is used for the permission check.
+
+This is _extremely_ powerful: you can perform permission checks based on who the current user is and _what is currently being interacted with_.  These runtime-based instance-level permission checks are a foundational technique for developing highly customizable and secure applications.
+
+### Step 7c: Run the webapp
+
+After checking out the `step7` branch, go ahead and run the web app:
+
+    $ mvn jetty:run
+
+Try visiting [localhost:8080](http://localhost:8080) and log in and out of the UI with your Jean-Luc Picard account (and other accounts), and see the page output change based on what permissions are assigned (or not)!
+
+Hit `ctl-C` (or `cmd-C` on a mac) to shut down the web app.
+
 ## Summary
 
 We hope you have found this introductory tutorial for Shiro-enabled webapps useful.  In coming editions of this tutorial, we will cover:
 
-* Shiro's extremely powerful [permissions](http://shiro.apache.org/permissions.html) and Permission-Based Access Control.
 * Plugging in different user data stores, like an RDBMS or NoSQL data store.
 
 ### Fixes and Pull Requests