You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shiro.apache.org by bd...@apache.org on 2016/10/21 20:08:01 UTC

svn commit: r1766119 [5/5] - in /shiro/site/publish: ./ 2010/03/18/ 2010/06/01/ 2010/09/14/ 2010/09/20/ 2010/09/24/ 2010/11/03/ 2011/01/06/ 2011/01/13/ 2011/02/10/ 2011/02/28/ 2011/03/14/ 2011/05/24/ 2011/06/30/ 2012/01/24/ 2012/03/13/ 2012/07/29/ 2013...

Modified: shiro/site/publish/webapp-tutorial.html
URL: http://svn.apache.org/viewvc/shiro/site/publish/webapp-tutorial.html?rev=1766119&r1=1766118&r2=1766119&view=diff
==============================================================================
--- shiro/site/publish/webapp-tutorial.html (original)
+++ shiro/site/publish/webapp-tutorial.html Fri Oct 21 20:08:00 2016
@@ -41,8 +41,13 @@
       <link rel="stylesheet" href="./assets/css/gh-pages/gh-fork-ribbon.ie.css" />
     <![endif]-->
 
+    <!-- syntax highlighting -->
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css" integrity="sha256-Zd1icfZ72UBmsId/mUcagrmN7IN5Qkrvh75ICHIQVTk=" crossorigin="anonymous" />
+    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/highlight.min.js" integrity="sha256-s63qpgPYoQk+wv3U6WZqioVJrwFNBTgD4dkeegLuwvo=" crossorigin="anonymous"></script>
+
     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
     <script type="text/javascript" src="./assets/js/jquery_googleanalytics/jquery.google-analytics.js"></script>
+    <script>hljs.initHighlightingOnLoad();</script>
     <script type="text/javascript">
         // initialize plugins
         jQuery(function() {
@@ -76,7 +81,7 @@
             <h1><a href="#securing-web-applications-with-apache-shiro" name="securing-web-applications-with-apache-shiro">Securing Web Applications with Apache Shiro</a></h1>
 <p>This document is an introductory step-by-step tutorial to securing a web application with Apache Shiro. It assumes an introductory knowledge of Shiro, and assumes familiarity with at least the following two introductory documents:</p>
 <ul>
-  <li><a href="http://www.infoq.com/articles/apache-shiro">Application Security with Apache Shiro</a></li>
+  <li><a href="https://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>
@@ -94,7 +99,7 @@
 </ul>
 <a id="overview"></a>
 <h2><a href="#overview" name="overview">Overview</a></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>
+<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="https://en.wikipedia.org/wiki/Java_servlet">Servlet</a> container, such as Tomcat or Jetty.</p>
 <h3><a href="#prerequisites" name="prerequisites">Prerequisites</a></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>
@@ -116,30 +121,30 @@
 <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    
+<pre><code class="bash">$ 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
+<pre><code class="bash">$ cd apache-shiro-tutorial-webapp
 </code></pre>
 <h3>3. Review project structure</h3>
 <p>After cloning the repo, your current <code>master</code> branch will have the following structure:</p>
-<pre><code>apache-shiro-tutorial-webapp/
-  |-- src/
-  |  |-- main/
-  |    |-- resources/
-  |      |-- logback.xml
-  |    |-- webapp/
-  |      |-- WEB-INF/
-  |        |-- web.xml
-  |      |-- home.jsp
-  |      |-- include.jsp
-  |      |-- index.jsp
-  |-- .gitignore
-  |-- .travis.yml
-  |-- LICENSE
-  |-- README.md
-  |-- pom.xml
+<pre><code class="nohighlight">    apache-shiro-tutorial-webapp/
+      |-- src/
+      |  |-- main/
+      |    |-- resources/
+      |      |-- logback.xml
+      |    |-- webapp/
+      |      |-- WEB-INF/
+      |        |-- web.xml
+      |      |-- home.jsp
+      |      |-- include.jsp
+      |      |-- index.jsp
+      |-- .gitignore
+      |-- .travis.yml
+      |-- LICENSE
+      |-- README.md
+      |-- pom.xml
 </code></pre>
 <p>Here is what each means:</p>
 <ul>
@@ -156,7 +161,7 @@
 </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 
+<pre><code class="bash">$ 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> to shut down the web app.</p>
@@ -164,7 +169,7 @@
 <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
+<pre><code class="bash">$ git checkout step1
 </code></pre>
 <p>Checking out this branch, you will find two changes:</p>
 <ol>
@@ -175,7 +180,7 @@
 <p>Shiro can be configured in many different ways in a web application, depending on the web and/or MVC framework you use. For example, you can configure Shiro via Spring, Guice, Tapestry, and many many more.</p>
 <p>To keep things simple for now, we&rsquo;ll start a Shiro environment by using Shiro&rsquo;s default (and very simple) <a href="http://shiro.apache.org/configuration.html">INI-based configuration</a>.</p>
 <p>If you checked out the <code>step1</code> branch, you&rsquo;ll see the contents of this new <code>src/main/webapp/WEB-INF/shiro.ini</code> file (header comments removed for brevity):</p>
-<pre><code>[main]
+<pre><code class="ini">[main]
 
 # Let&#39;s use some in-memory caching to reduce the number of runtime lookups against a remote user store.
 # A real application might want to use a more robust caching solution (e.g. ehcache or a
@@ -193,7 +198,7 @@ securityManager.cacheManager = $cacheMan
 <h3>1b: Enable Shiro in <code>web.xml</code></h3>
 <p>While we have a <code>shiro.ini</code> configuration, we need to actually <em>load</em> it and start a new Shiro environment and make that environment available to the web application.</p>
 <p>We do all of this by adding a few things to the existing <code>src/main/webapp/WEB-INF/web.xml</code> file:</p>
-<pre><code>&lt;listener&gt;
+<pre><code class="xml">&lt;listener&gt;
     &lt;listener-class&gt;org.apache.shiro.web.env.EnvironmentLoaderListener&lt;/listener-class&gt;
 &lt;/listener&gt;
 
@@ -221,17 +226,17 @@ securityManager.cacheManager = $cacheMan
 </ul>
 <h3>1c: Run the webapp</h3>
 <p>After checking out the <code>step1</code> branch, go ahead and run the web app:</p>
-<pre><code>$ mvn jetty:run
+<pre><code class="bash">$ mvn jetty:run
 </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.
+<pre><code class="nohighlight">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> to shut down the web app.</p>
 <a id="step2"></a>
 <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
+<pre><code class="bash">$ 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>
@@ -239,13 +244,13 @@ securityManager.cacheManager = $cacheMan
 <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>In this sense a Realm is essentially a security-specific <a href="https://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 sources 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>
 </blockquote>
 <p>So, we need to configure a Realm so we can access users.</p>
 <h3>2a: Set up Stormpath</h3>
 <p>In the spirit of keeping this tutorial as simple as possible, without introducing complexity or scope that distracts us from the purpose of learning Shiro, we&rsquo;ll use one of the simplest realms we can: a Stormpath realm.</p>
-<p><a href="http://stormpath.com/">Stormpath</a> is a cloud hosted user management service, totally free for development purposes. This means that after enabling Stormpath, you&rsquo;ll have the following ready to go:</p>
+<p><a href="https://stormpath.com/">Stormpath</a> is a cloud hosted user management service, totally free for development purposes. This means that after enabling Stormpath, you&rsquo;ll have the following ready to go:</p>
 <ul>
   <li>A user interface for managing Applications, Directories, Accounts and Groups. Shiro does not provide this at all, so this will be convenient and save time while you go through this tutorial.</li>
   <li>A secure storage mechanism for user passwords. Your application never needs to worry about password security, password comparisons or storing passwords. While Shiro can do these things, you would have to configure them and be aware of cryptographic concepts. Stormpath automates password security so you (and Shiro) don&rsquo;t need to worry about it or be on the hook for &lsquo;getting it right&rsquo;.</li>
@@ -269,29 +274,29 @@ securityManager.cacheManager = $cacheMan
   <li>
     <p>On the Account Details page, in the <strong>Security Credentials</strong> section, click <strong>Create API Key</strong> under <strong>Api Keys</strong>.</p>
     <p>This will generate your API Key and download it to your computer as an <code>apiKey.properties</code> file. If you open the file in a text editor, you will see something similar to the following:</p>
-    <pre><code> apiKey.id = 144JVZINOF5EBNCMG9EXAMPLE
- apiKey.secret = lWxOiKqKPNwJmSldbiSkEbkNjgh2uRSNAb+AEXAMPLE
+    <pre><code class="ini">apiKey.id = 144JVZINOF5EBNCMG9EXAMPLE
+apiKey.secret = lWxOiKqKPNwJmSldbiSkEbkNjgh2uRSNAb+AEXAMPLE
 </code></pre>
   </li>
   <li>
     <p>Save this file in a secure location, such as your home directory in a hidden <code>.stormpath</code> directory. For example:</p>
-    <pre><code>$HOME/.stormpath/apiKey.properties
+    <pre><code class="bash">$HOME/.stormpath/apiKey.properties
 </code></pre>
   </li>
   <li>
     <p>Also change the file permissions to ensure only you can read this file. For example, on *nix operating systems:</p>
-    <pre><code>$ chmod go-rwx $HOME/.stormpath/apiKey.properties
+    <pre><code class="bash">$ chmod go-rwx $HOME/.stormpath/apiKey.properties
 $ chmod u-w $HOME/.stormpath/apiKey.properties
 </code></pre>
   </li>
 </ol>
-<p>On Windows, you can <a href="http://msdn.microsoft.com/en-us/library/bb727008.aspx">set file permissions similarly</a>.</p>
+<p>On Windows, you can <a href="https://msdn.microsoft.com/en-us/library/bb727008.aspx">set file permissions similarly</a>.</p>
 <h4><a href="#retrieve-the-default-stormpath-application" name="retrieve-the-default-stormpath-application">Retrieve the default Stormpath Application</a></h4>
 <p>When you signed up for Stormpath, an empty application was automatically created for you. It&rsquo;s called: <code>My Application</code>.</p>
 <p>We have to register our web application with Stormpath to allow the app to use Stormpath for user management and authentication. In order to register our web application with the <code>My Application</code> Stormpath application, we need to know some information. Fortunately, we can retrieve this information using the Stormpath API.</p>
 <p>First, we need the location of your tenant from Stormpath. Here&rsquo;s how you get that:</p>
-<pre><code>curl -i --user $YOUR_API_KEY_ID:$YOUR_API_KEY_SECRET \
-    &#39;https://api.stormpath.com/v1/tenants/current&#39;
+<pre><code class="bash">curl -i --user $YOUR_API_KEY_ID:$YOUR_API_KEY_SECRET \
+&#39;https://api.stormpath.com/v1/tenants/current&#39;
 </code></pre>
 <p>where:</p>
 <ul>
@@ -299,7 +304,7 @@ $ chmod u-w $HOME/.stormpath/apiKey.prop
   <li>$YOUR_API_KEY_SECRET is the apiKey.secret value in apiKey.properties</li>
 </ul>
 <p>You&rsquo;ll get a response like this:</p>
-<pre><code>HTTP/1.1 302 Found
+<pre><code class="nohighlight">HTTP/1.1 302 Found
 Date: Fri, 28 Aug 2015 18:34:51 GMT
 Location: https://api.stormpath.com/v1/tenants/sOmELoNgRaNDoMIdHeRe
 Server: Apache
@@ -309,9 +314,9 @@ Content-Length: 0
 Connection: keep-alive
 </code></pre>
 <p>Notice the <code>Location</code> header. This is the location of your Stormpath tenant. Now, we can retrieve the location of the <code>My Application</code> Stormpath application, again using the API:</p>
-<pre><code>curl -u $API_KEY_ID:$API_KEY_SECRET \
-    -H &quot;Accept: application/json&quot; \
-    &#39;$TENANT_HREF/applications?name=My%20Application&#39;
+<pre><code class="bash">curl -u $API_KEY_ID:$API_KEY_SECRET \
+     -H &quot;Accept: application/json&quot; \
+     &#39;$TENANT_HREF/applications?name=My%20Application&#39;
 </code></pre>
 <p>where: </p>
 <ul>
@@ -320,7 +325,7 @@ Connection: keep-alive
   <li>$TENANT_HREF is the value of the <code>Location</code> header from the previous step</li>
 </ul>
 <p>The response from this has a lot of information in it. Here’s an example excerpt from the response:</p>
-<pre><code>{
+<pre><code class="json">{
     ...
     &quot;href&quot;: &quot;https://api.stormpath.com/v1/applications/aLoNGrAnDoMAppIdHeRe&quot;,
     &quot;name&quot;: &quot;My Application&quot;,
@@ -335,7 +340,7 @@ Connection: keep-alive
 <p>Make note of your top-level <code>href</code> from above - we will use this href in the <code>shiro.ini</code> configuration next.</p>
 <h4><a href="#create-an-application-test-user-account" name="create-an-application-test-user-account">Create an application test user account</a></h4>
 <p>Now that we have an application, we&rsquo;ll want to create a sample/test user for that application:</p>
-<pre><code>curl --request POST --user $YOUR_API_KEY_ID:$YOUR_API_KEY_SECRET \
+<pre><code class="bash">curl --request 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;{
@@ -357,7 +362,7 @@ Connection: keep-alive
 <h3>2b: Configure the Realm in <code>shiro.ini</code></h3>
 <p>Once you choose at least one user store to connect to for Shiro&rsquo;s needs, we&rsquo;ll need to configure a <code>Realm</code> that represents that data store and then tell the Shiro <code>SecurityManager</code> about it.</p>
 <p>If you&rsquo;ve checked out the <code>step2</code> branch, you&rsquo;ll notice the <code>src/main/webapp/WEB-INF/shiro.ini</code> file&rsquo;s <code>[main]</code> section now has the following additions:</p>
-<pre style="white-space: pre;"><code>
+<pre style="white-space: pre;"><code class="ini">
 # Configure a Realm to connect to a user datastore.  In this simple tutorial, we'll just point to Stormpath since it
 # takes 5 minutes to set up:
 stormpathClient = com.stormpath.shiro.client.ClientFactory
@@ -383,10 +388,10 @@ securityManager.realm = $stormpathRealm
 </ul>
 <h3>2d: 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
+<pre><code class="bash">$ mvn jetty:run
 </code></pre>
 <p>This time, you will see log output similar to the following, indicating that Shiro and the new Realm are configured properly in your webapp:</p>
-<pre><code>16:08:25.466 [main] INFO  o.a.shiro.web.env.EnvironmentLoader - Starting Shiro environment initialization.
+<pre><code class="nohighlight">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>
@@ -395,7 +400,7 @@ securityManager.realm = $stormpathRealm
 <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
+<pre><code class="bash">$ git checkout step3
 </code></pre>
 <p>This checkout will load the following 2 additions:</p>
 <ul>
@@ -404,7 +409,7 @@ securityManager.realm = $stormpathRealm
 </ul>
 <h3>Step 3a: Enable Shiro form login and logout support</h3>
 <p>The <code>step3</code> branch&rsquo;s <code>src/main/webapp/WEB-INF/shiro.ini</code> file contains the following 2 additions:</p>
-<pre><code>[main]
+<pre><code class="ini">[main]
 
 shiro.loginUrl = /login.jsp
 
@@ -416,16 +421,16 @@ shiro.loginUrl = /login.jsp
 </code></pre>
 <h4><code>shiro.*</code> lines</h4>
 <p>At the top of the <code>[main]</code> section, there is a new line:</p>
-<pre><code>shiro.loginUrl = /login.jsp
+<pre><code class="ini">shiro.loginUrl = /login.jsp
 </code></pre>
 <p>This is a special configuration directive that tells Shiro &ldquo;For any of Shiro&rsquo;s <a href="http://shiro.apache.org/web.html#Web-DefaultFilters">default filters</a> that have a <code>loginUrl</code> property, I want that property value to be set to <code>/login.jsp</code>.&rdquo;</p>
 <p>This allows Shiro&rsquo;s default <code>authc</code> filter (by default, a <a href="http://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/filter/authc/FormAuthenticationFilter.html"><code>FormAuthenticationFilter</code></a>) to know about the login page. This is necessary for the <code>FormAuthenticationFilter</code> to work correctly.</p>
 <h4>The <code>[urls]</code> section</h4>
 <p>The <code>[urls]</code> section is a new <a href="http://shiro.apache.org/web.html#Web-%7B%7B%5Curls%5C%7D%7D">web-specific INI section</a>.</p>
-<p>This section allows you to use a very succinct name/value pair syntax to tell shiro how to filter request for any given URL path. All paths in <code>[urls]</code> are relative to the web application&rsquo;s [<code>HttpServletRequest.getContextPath()</code>](<a href="http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/servlet/http/HttpServletRequest.html#getContextPath()">http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/servlet/http/HttpServletRequest.html#getContextPath()</a>) value.</p>
+<p>This section allows you to use a very succinct name/value pair syntax to tell shiro how to filter request for any given URL path. All paths in <code>[urls]</code> are relative to the web application&rsquo;s [<code>HttpServletRequest.getContextPath()</code>](<a href="http://docs.oracle.com/javaee/1.3/api/javax/servlet/http/HttpServletRequest.html#getContextPath()">http://docs.oracle.com/javaee/1.3/api/javax/servlet/http/HttpServletRequest.html#getContextPath()</a>) value.</p>
 <p>These name/value pairs offer an extremely powerful way to filter requests, allowing for all sorts of security rules. A deeper coverage of urls and filter chains is outside the scope of this document, but please do <a href="http://shiro.apache.org/web.html#Web-%7B%7B%5Curls%5C%7D%7D">read more about it</a> if you&rsquo;re interested.</p>
 <p>For now, we&rsquo;ll cover the two lines that were added:</p>
-<pre><code>/login.jsp = authc
+<pre><code class="ini">/login.jsp = authc
 /logout = logout
 </code></pre>
 <ul>
@@ -445,7 +450,7 @@ shiro.loginUrl = /login.jsp
 <p>Our login.jsp form just uses the default <code>username</code>, <code>password</code>, and <code>rememberMe</code> form field names. These names 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
+<pre><code class="bash">$ 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>
@@ -456,7 +461,7 @@ shiro.loginUrl = /login.jsp
 <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
+<pre><code class="bash">$ git checkout step4
 </code></pre>
 <p>This step makes some additions to our <code>home.jsp</code> page:</p>
 <ul>
@@ -466,13 +471,13 @@ shiro.loginUrl = /login.jsp
 <p>This type of UI customization is very common for a navigation bar, with user controls on the upper right of the screen.</p>
 <h3>Step 4a: Add the Shiro Tag Library Declaration</h3>
 <p>The <code>home.jsp</code> file was modified to include two lines at the top:</p>
-<pre><code>&lt;%@ taglib prefix=&quot;shiro&quot; uri=&quot;http://shiro.apache.org/tags&quot; %&gt;
+<pre><code class="html">&lt;%@ taglib prefix=&quot;shiro&quot; uri=&quot;http://shiro.apache.org/tags&quot; %&gt;
 &lt;%@ taglib prefix=&quot;c&quot; uri=&quot;http://java.sun.com/jsp/jstl/core&quot; %&gt;
 </code></pre>
 <p>These two JSP page directives allow the Core (<code>c:</code>) and Shiro (<code>shiro:</code>) taglibraries in the page.</p>
 <h3>Step 4b: Add Shiro Guest and User tags</h3>
 <p>The <code>home.jsp</code> file was further modified in the page body (right after the <code>&lt;h1&gt;</code> welcome message) to include <em>both</em> the <code>&lt;shiro:guest&gt;</code> and <code>&lt;shiro:user&gt;</code> tags:</p>
-<pre><code>&lt;p&gt;Hi &lt;shiro:guest&gt;Guest&lt;/shiro:guest&gt;&lt;shiro:user&gt;
+<pre><code class="html">&lt;p&gt;Hi &lt;shiro:guest&gt;Guest&lt;/shiro:guest&gt;&lt;shiro:user&gt;
 &lt;%
     //This should never be done in a normal page and should exist in a proper MVC controller of some sort, but for this
     //tutorial, we&#39;ll just pull out Stormpath Account data from Shiro&#39;s PrincipalCollection to reference in the
@@ -492,17 +497,17 @@ shiro.loginUrl = /login.jsp
   <li><code>&lt;shiro:user&gt;</code>: This tag will only display its internal contents if the current Shiro <code>Subject</code> is an application &lsquo;user&rsquo;. Shiro defines a <code>user</code> as any <code>Subject</code> that is <em>currently</em> logged in to (authenticated with) the application or one that is remembered from a previous login (using Shiro&rsquo;s &lsquo;remember me&rsquo; functionality).</li>
 </ul>
 <p>The above code snippet will render the following if the Subject is a guest:</p>
-<pre><code>Hi Guest! (Log in)
+<pre><code class="html">Hi Guest! (Log in)
 </code></pre>
 <p>where &lsquo;Log in&rsquo; is a hyperlink to <code>/login.jsp</code></p>
 <p>It will render the following if the Subject is a &lsquo;user&rsquo;:</p>
-<pre><code>Hi jsmith! (Log out)
+<pre><code class="html">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
+<pre><code class="bash">$ 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> to shut down the web app.</p>
@@ -511,7 +516,7 @@ shiro.loginUrl = /login.jsp
 <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
+<pre><code class="bash">$ git checkout step5
 </code></pre>
 <p>Step 5 introduces the following 3 changes:</p>
 <ol>
@@ -523,21 +528,22 @@ shiro.loginUrl = /login.jsp
 <p>A new <code>src/main/webapp/account</code> directory was added. This directory (and all paths below it) simulates a &lsquo;private&rsquo; or &lsquo;authenticated only&rsquo; section of a website that you might want to restrict to only logged in users. The <code>src/main/webapp/account/index.jsp</code> file is just a placeholder for a simulated &lsquo;home account&rsquo; page.</p>
 <h3>Step 5b: Configure <code>shiro.ini</code></h3>
 <p><code>shiro.ini</code> was modified by adding the following line at the end of the <code>[urls]</code> section:</p>
-<pre><code>/account/** = authc
+<pre><code class="ini">/account/** = authc
 </code></pre>
 <p>This <a href="http://shiro.apache.org/web.html#Web-FilterChainDefinitions">Shiro filter chain definition</a> means &ldquo;Any requests to <code>/account</code> (or any of its sub-paths) must be authenticated&rdquo;.</p>
 <p>But what happens if someone tries to access that path or any of its children paths?</p>
 <p>Do you remember in Step 3 when we added the following line to the <code>[main]</code> section:</p>
-<pre><code>shiro.loginUrl = /login.jsp
+<pre><code class="ini">shiro.loginUrl = /login.jsp
 </code></pre>
 <p>This line automatically configured the <code>authc</code> filter with our webapp&rsquo;s login URL.</p>
 <p>Based on this line of config, the <code>authc</code> filter is now smart enough to know that if the current Subject is not authenticated when accessing <code>/account</code>, it will automatically redirect the <code>Subject</code> to the <code>/login.jsp</code> page. After successful login, it will then automatically redirect the user back to the page they were trying to access (<code>/account</code>). Convenient!</p>
 <h3>Step 5c: Update our home page</h3>
 <p>The final change for Step 5 is to update the <code>/home.jsp</code> page to let the user know they can access the new part of the web site.</p>
 <p>These lines were added below the welcome message:</p>
-<pre><code>&lt;shiro:authenticated&gt;&lt;p&gt;Visit your &lt;a href=&quot;&lt;c:url value=&quot;/account&quot;/&gt;&quot;&gt;account page&lt;/a&gt;.&lt;/p&gt;&lt;/shiro:authenticated&gt;
-&lt;shiro:notAuthenticated&gt;&lt;p&gt;If you want to access the authenticated-only &lt;a href=&quot;&lt;c:url value=&quot;/account&quot;/&gt;&quot;&gt;account page&lt;/a&gt;,
-    you will need to log-in first.&lt;/p&gt;&lt;/shiro:notAuthenticated&gt;
+<pre><code class="html">&lt;shiro:authenticated&gt;&lt;p&gt;Visit your &lt;a href=&quot;&lt;c:url value=&quot;/account&quot;/&gt;&quot;&gt;account page&lt;/a&gt;.&lt;/p&gt;&lt;/shiro:authenticated&gt;
+&lt;shiro:notAuthenticated&gt;
+  &lt;p&gt;If you want to access the authenticated-only &lt;a href=&quot;&lt;c:url value=&quot;/account&quot;/&gt;&quot;&gt;account page&lt;/a&gt;, 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>
@@ -545,7 +551,7 @@ shiro.loginUrl = /login.jsp
 <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
+<pre><code class="bash">$ 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> to shut down the web app.</p>
@@ -553,7 +559,7 @@ shiro.loginUrl = /login.jsp
 <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
+<pre><code class="bash">$ 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>
@@ -570,11 +576,11 @@ shiro.loginUrl = /login.jsp
 <p>Once you&rsquo;ve created the groups, add the <code>Jean-Luc Picard</code> account to the <code>Captains</code> and <code>Officers</code> groups. You might want to create some ad-hoc accounts and add them to whatever groups you like. Make sure some of the accounts don&rsquo;t overlap groups so you can see changes based on separate Groups assigned to user accounts.</p>
 <h3>Step 6b: Role Based Access Control (RBAC) Tags</h3>
 <p>We update the <code>/home.jsp</code> page to let the user know what roles they have and which ones they don&rsquo;t. These messages are added in a new <code>&lt;h2&gt;Roles&lt;/h2&gt;</code> section of the home page:</p>
-<pre><code>&lt;h2&gt;Roles&lt;/h2&gt;
+<pre><code class="html">&lt;h2&gt;Roles&lt;/h2&gt;
 
 &lt;p&gt;Here are the roles you have and don&#39;t have. Log out and log back in under different user
     accounts to see different roles.&lt;/p&gt;
-
+    
 &lt;h3&gt;Roles you have:&lt;/h3&gt;
 
 &lt;p&gt;
@@ -598,7 +604,7 @@ shiro.loginUrl = /login.jsp
 <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
+<pre><code class="bash">$ 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> to shut down the web app.</p>
@@ -610,8 +616,8 @@ shiro.loginUrl = /login.jsp
 <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 Stormpath 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 \
+<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="https://docs.stormpath.com/rest/product-guide/latest/reference.html#custom-data">custom data</a>:</p>
+<pre><code class="bash">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;{
@@ -633,7 +639,7 @@ shiro.loginUrl = /login.jsp
 <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 permission 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;
+<pre><code class="html">&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;
@@ -641,23 +647,23 @@ shiro.loginUrl = /login.jsp
 &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!
+<pre><code class="html">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!
+<pre><code class="html">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; ...
+<pre><code class="html">&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
+<pre><code class="bash">$ 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> to shut down the web app.</p>
@@ -667,7 +673,7 @@ You may edit the user!
   <li>Plugging in different user data stores, like an RDBMS or NoSQL data store.</li>
 </ul>
 <h3><a href="#fixes-and-pull-requests" name="fixes-and-pull-requests">Fixes and Pull Requests</a></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>
+<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>
 
         </div>
 

Modified: shiro/site/publish/what-is-shiro.html
URL: http://svn.apache.org/viewvc/shiro/site/publish/what-is-shiro.html?rev=1766119&r1=1766118&r2=1766119&view=diff
==============================================================================
--- shiro/site/publish/what-is-shiro.html (original)
+++ shiro/site/publish/what-is-shiro.html Fri Oct 21 20:08:00 2016
@@ -41,8 +41,13 @@
       <link rel="stylesheet" href="./assets/css/gh-pages/gh-fork-ribbon.ie.css" />
     <![endif]-->
 
+    <!-- syntax highlighting -->
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css" integrity="sha256-Zd1icfZ72UBmsId/mUcagrmN7IN5Qkrvh75ICHIQVTk=" crossorigin="anonymous" />
+    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/highlight.min.js" integrity="sha256-s63qpgPYoQk+wv3U6WZqioVJrwFNBTgD4dkeegLuwvo=" crossorigin="anonymous"></script>
+
     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
     <script type="text/javascript" src="./assets/js/jquery_googleanalytics/jquery.google-analytics.js"></script>
+    <script>hljs.initHighlightingOnLoad();</script>
     <script type="text/javascript">
         // initialize plugins
         jQuery(function() {
@@ -94,7 +99,7 @@
 
 <p>Standard JAAS and EJB security models couldn't cut it - they required static definitions that only programmers could change, requiring the application to re-deployed all over again. And although those 20% of clients required dynamic functionality, there were many more that would have liked that capability, even though it wasn't a pure requirement for their applications. I quickly realized how useful something like this was and tried to see how I could achieve what many people wanted.</p>
 
-<p>Like most of the Java community, I looked into <a class="external-link" href="http://java.sun.com/products/jaas" rel="nofollow">JAAS</a> to see if it could do what I wanted. After all, it was really the only security technology out there widely accessible to Java developers at the time. I did a <em>lot</em> of research, looking for ways that I might be able to coerce JAAS into doing what I wanted. Sometimes it came close. JAAS Authentication could meet my needs with a decent amount of effort, but JAAS Authorization didn't even come close.</p>
+<p>Like most of the Java community, I looked into <a class="external-link" href="http://docs.oracle.com/javase/7/docs/technotes/guides/security/jaas/JAASRefGuide.html" rel="nofollow">JAAS</a> to see if it could do what I wanted. After all, it was really the only security technology out there widely accessible to Java developers at the time. I did a <em>lot</em> of research, looking for ways that I might be able to coerce JAAS into doing what I wanted. Sometimes it came close. JAAS Authentication could meet my needs with a decent amount of effort, but JAAS Authorization didn't even come close.</p>
 
 <p>JAAS is tied too heavily tied to virtual machine-level concerns. As an application architect, I usually didn't care one bit about whether or not a <em>Class</em> could execute inside the virtual machine.  What I really wanted to control is whether or not the <em>current user</em> could execute a given method, often based on the method's arguments. So, I hobbled a bit, creating some functionality to piggy-back JAAS and custom-coded the rest. The result was only usable on a few applications and wasn't nearly as robust as I wanted.</p>
 

Modified: shiro/site/publish/wiki-todos.html
URL: http://svn.apache.org/viewvc/shiro/site/publish/wiki-todos.html?rev=1766119&r1=1766118&r2=1766119&view=diff
==============================================================================
--- shiro/site/publish/wiki-todos.html (original)
+++ shiro/site/publish/wiki-todos.html Fri Oct 21 20:08:00 2016
@@ -41,8 +41,13 @@
       <link rel="stylesheet" href="./assets/css/gh-pages/gh-fork-ribbon.ie.css" />
     <![endif]-->
 
+    <!-- syntax highlighting -->
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/default.min.css" integrity="sha256-Zd1icfZ72UBmsId/mUcagrmN7IN5Qkrvh75ICHIQVTk=" crossorigin="anonymous" />
+    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/highlight.min.js" integrity="sha256-s63qpgPYoQk+wv3U6WZqioVJrwFNBTgD4dkeegLuwvo=" crossorigin="anonymous"></script>
+
     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
     <script type="text/javascript" src="./assets/js/jquery_googleanalytics/jquery.google-analytics.js"></script>
+    <script>hljs.initHighlightingOnLoad();</script>
     <script type="text/javascript">
         // initialize plugins
         jQuery(function() {