| <h1><a name="10MinuteTutorial-10MinuteTutorialonApacheShiro"></a>10 Minute Tutorial on Apache Shiro</h1> |
| |
| <div class="addthis_toolbox addthis_default_style"> |
| <a class="addthis_button_compact" href="http://www.addthis.com/bookmark.php?v=250&pubid=ra-4d66ef016022c3bd">Share</a> |
| <span class="addthis_separator">|</span> |
| <a class="addthis_button_preferred_1"></a> |
| <a class="addthis_button_preferred_2"></a> |
| <a class="addthis_button_preferred_3"></a> |
| <a class="addthis_button_preferred_4"></a> |
| </div> |
| <script type="text/javascript">var addthis_config = {"data_track_clickback": true};</script> |
| <script type="text/javascript" src="http://s7.addthis.com/js/250/addthis_widget.js#pubid=ra-4d66ef016022c3bd"></script> |
| |
| |
| <h2><a name="10MinuteTutorial-Introduction"></a>Introduction</h2> |
| |
| <p>Welcome to Apache Shiro's 10 Minute Tutoral! </p> |
| |
| <p>By going through this quick and simple tutorial you should fully understand how a developer uses Shiro in their |
| application. And you should be able to do it in under 10 minutes.</p> |
| |
| <h2><a name="10MinuteTutorial-Overview"></a>Overview</h2> |
| |
| <p>What is Apache Shiro?</p> |
| |
| <p>Apache Shiro is a powerful and easy to use Java security framework that offers developers an intuitive yet |
| comprehensive solution to authentication, authorization, cryptography, and session management.</p> |
| |
| <p>In practical terms, it achieves to manage all facets of your application's security, while keeping out of the way as |
| much as possible. It is built on sound interface-driven design and OO principles, enabling custom behavior wherever |
| you can imagine it. But with sensible defaults for everything, it is as "hands off" as application security can be. |
| At least that's what we strive for.</p> |
| |
| <p>What can Apache Shiro do?</p> |
| |
| <p>A lot <img align="middle" class="emoticon" src="https://cwiki.apache.org/confluence/images/icons/emoticons/smile.png" |
| height="20" width="20" alt="" border="0">. But we don't want to bloat the QuickStart. Please check out our |
| <a href="features.html" title="Features">Features</a> page if you'd like to see what it can do for you. Also, if |
| you're curious on how we got started and why we exist, please see the <a href="what-is-shiro.html" |
| title="What is Shiro">Shiro History and |
| Mission</a> page.</p> |
| |
| <p>Ok. Now let's actually do something!</p> |
| |
| <div class="panelMacro"> |
| <table class="infoMacro"> |
| <colgroup span="1"> |
| <col span="1" width="24"> |
| <col span="1"> |
| </colgroup> |
| <tr> |
| <td colspan="1" rowspan="1" valign="top"><img align="middle" |
| src="https://cwiki.apache.org/confluence/images/icons/emoticons/information.png" |
| width="16" height="16" alt="" border="0"></td> |
| <td colspan="1" rowspan="1">Shiro can be run in any environment, from the simplest command line application |
| to the biggest enterprise web and clustered applications, but we'll use the simplest possible example in |
| a simple <tt>main</tt> method for this QuickStart so you can get a feel for the API. |
| </td> |
| </tr> |
| </table> |
| </div> |
| |
| <h2><a name="10MinuteTutorial-Download"></a>Download</h2> |
| |
| <ol> |
| <li>Ensure you have JDK 1.5+ and Maven 2.2+ installed.</li> |
| <li>Download the lastest "Source Code Distribution" from the <a href="download.html" title="Download">Download</a> |
| page. In this example, we're using the 1.1.0 release distribution. |
| </li> |
| <li>Unzip the source package: |
| <div class="code panel" style="border-width: 1px;"> |
| <div class="codeContent panelContent"> |
| <pre class="code-java"> |
| > unzip shiro-root-1.2.0-source-release.zip |
| </pre> |
| </div> |
| </div> |
| </li> |
| <li>Enter the quickstart directory: |
| <div class="code panel" style="border-width: 1px;"> |
| <div class="codeContent panelContent"> |
| <pre class="code-java"> |
| > cd shiro-root-1.2.0/samples/quickstart |
| </pre> |
| </div> |
| </div> |
| </li> |
| <li>Run the QuickStart: |
| <div class="code panel" style="border-width: 1px;"> |
| <div class="codeContent panelContent"> |
| <pre class="code-java"> |
| > mvn compile exec:java |
| </pre> |
| </div> |
| </div> |
| <p>This target will just print out some log messages to let you know what is going on and then exit. While |
| reading this quickstart, feel free to look at the code found under <tt>samples/quickstart/src/main/java/Quickstart.java</tt>. |
| Change that file and run the above <tt>mvn compile exec:java</tt> command as often as you like.</p></li> |
| </ol> |
| |
| |
| <h2><a name="10MinuteTutorial-Quickstart.java"></a>Quickstart.java</h2> |
| |
| <p>The <tt>Quickstart.java</tt> file referenced above contains all the code that will get you familiar with the API. Now |
| lets break it down in chunks here so you can easily understand what is going on.</p> |
| |
| <p>In almost all environments, you can obtain the currently executing user via the following call:</p> |
| |
| <p></p> |
| |
| <div class="code panel" style="border-width: 1px;"> |
| <div class="codeContent panelContent"> |
| <pre class="code-java"> |
| Subject currentUser = SecurityUtils.getSubject(); |
| </pre> |
| </div> |
| </div> |
| |
| <p>Using <tt><a class="external-link" |
| href="static/current/apidocs/org/apache/shiro/SecurityUtils.html">SecurityUtils</a>.<a |
| class="external-link" href="static/current/apidocs/org/apache/shiro/SecurityUtils.html#getSubject()">getSubject()</a></tt>, |
| we can obtain the currently executing <tt><a class="external-link" |
| href="static/current/apidocs/org/apache/shiro/subject/Subject.html">Subject</a></tt>. |
| A <em>Subject</em> is just a security-specific "view" of an application User. We actually wanted to call it 'User' |
| since that "just makes sense", but we decided against it: too many applications have existing APIs that already have |
| their own User classes/frameworks, and we didn't want to conflict with those. Also, in the security world, the term |
| <tt>Subject</tt> is actually the recognized nomenclature. Ok, moving on...</p> |
| |
| <p>The <tt>getSubject()</tt> call in a standalone application might return a <tt>Subject</tt> based on user data in an |
| application-specific location, and in a server environment (e.g. web app), it acquires the <tt>Subject</tt> based on |
| user data associated with current thread or incoming request.</p> |
| |
| <p>Now that you have a <tt>Subject</tt>, what can you do with it?</p> |
| |
| <p>If you want to make things available to the user during their current session with the application, you can get their |
| session:</p> |
| |
| <p></p> |
| |
| <div class="code panel" style="border-width: 1px;"> |
| <div class="codeContent panelContent"> |
| <pre class="code-java"> |
| Session session = currentUser.getSession(); |
| session.setAttribute( <span class="code-quote">"someKey"</span>, <span class="code-quote">"aValue"</span> ); |
| </pre> |
| </div> |
| </div> |
| |
| <p>The <tt>Session</tt> is a Shiro-specific instance that provides most of what you're used to with regular HttpSessions |
| but with some extra goodies and one <b>big</b> difference: it does not require an HTTP environment!</p> |
| |
| <p>If deploying inside a web application, by default the <tt>Session</tt> will be <tt>HttpSession</tt> based. But, in a |
| non-web environment, like this simple Quickstart, Shiro will automatically use its Enterprise Session Management by |
| default. This means you get to use the same API in your applications, in any tier, regardless of deployment |
| environment. This opens a whole new world of applications since any application requiring sessions does not need to |
| be forced to use the <tt>HttpSession</tt> or EJB Stateful Session Beans. And, any client technology can now share |
| session data.</p> |
| |
| <p>So now you can acquire a <tt>Subject</tt> and their <tt>Session</tt>. What about the <em>really</em> useful stuff |
| like checking if they are allowed to do things, like checking against roles and permissions?</p> |
| |
| <p>Well, we can only do those checks for a known user. Our <tt>Subject</tt> instance above represents the current user, |
| but <em>who</em> is the current user? Well, they're anonymous - that is, until they log in at least once. So, let's |
| do that:</p> |
| |
| <div class="code panel" style="border-width: 1px;"> |
| <div class="codeContent panelContent"> |
| <pre class="code-java"> |
| <span class="code-keyword">if</span> ( !currentUser.isAuthenticated() ) { |
| <span class="code-comment">//collect user principals and credentials in a gui specific manner |
| </span> <span class="code-comment">//such as username/password html form, X509 certificate, OpenID, etc. |
| </span> <span class="code-comment">//We'll use the username/password example here since it is the most common. |
| </span> <span class="code-comment">//(<span class="code-keyword">do</span> you know what movie <span |
| class="code-keyword">this</span> is from? ;) |
| </span> UsernamePasswordToken token = <span class="code-keyword">new</span> UsernamePasswordToken(<span |
| class="code-quote">"lonestarr"</span>, <span class="code-quote">"vespa"</span>); |
| <span class="code-comment">//<span class="code-keyword">this</span> is all you have to <span |
| class="code-keyword">do</span> to support 'remember me' (no config - built in!): |
| </span> token.setRememberMe(<span class="code-keyword">true</span>); |
| currentUser.login(token); |
| } |
| </pre> |
| </div> |
| </div> |
| |
| <p>That's it! It couldn't be easier.</p> |
| |
| <p>But what if their login attempt fails? You can catch all sorts of specific exceptions that tell you exactly what |
| happened and allows you to handle and react accordingly:</p> |
| |
| <div class="code panel" style="border-width: 1px;"> |
| <div class="codeContent panelContent"> |
| <pre class="code-java"> |
| <span class="code-keyword">try</span> { |
| currentUser.login( token ); |
| <span class="code-comment">//<span class="code-keyword">if</span> no exception, that's it, we're done! |
| </span>} <span class="code-keyword">catch</span> ( UnknownAccountException uae ) { |
| <span class="code-comment">//username wasn't in the system, show them an error message? |
| </span>} <span class="code-keyword">catch</span> ( IncorrectCredentialsException ice ) { |
| <span class="code-comment">//password didn't match, <span class="code-keyword">try</span> again? |
| </span>} <span class="code-keyword">catch</span> ( LockedAccountException lae ) { |
| <span class="code-comment">//account <span class="code-keyword">for</span> that username is locked - can't login. Show them a message? |
| </span>} |
| ... more types exceptions to check <span class="code-keyword">if</span> you want ... |
| } <span class="code-keyword">catch</span> ( AuthenticationException ae ) { |
| <span class="code-comment">//unexpected condition - error? |
| </span>} |
| </pre> |
| </div> |
| </div> |
| |
| <p>There are many different types of exceptions you can check, or throw your own for custom conditions Shiro might not |
| account for. See the <a class="external-link" |
| href="static/current/apidocs/org/apache/shiro/authc/AuthenticationException.html">AuthenticationException |
| JavaDoc</a> for more. </p> |
| |
| <div class="panelMacro"> |
| <table class="tipMacro"> |
| <colgroup span="1"> |
| <col span="1" width="24"> |
| <col span="1"> |
| </colgroup> |
| <tr> |
| <td colspan="1" rowspan="1" valign="top"><img align="middle" |
| src="https://cwiki.apache.org/confluence/images/icons/emoticons/check.png" |
| width="16" height="16" alt="" border="0"></td> |
| <td colspan="1" rowspan="1"><b>Handy Hint</b><br clear="none">Security best practice is to give generic |
| login failure messages to users because you do not want to aid an attacker trying to break into your |
| system. |
| </td> |
| </tr> |
| </table> |
| </div> |
| |
| <p>Ok, so by now, we have a logged in user. What else can we do?</p> |
| |
| <p>Let's say who they are:</p> |
| |
| <p></p> |
| |
| <div class="code panel" style="border-width: 1px;"> |
| <div class="codeContent panelContent"> |
| <pre class="code-java"> |
| <span class="code-comment">//print their identifying principal (in <span class="code-keyword">this</span> <span |
| class="code-keyword">case</span>, a username): |
| </span>log.info( <span class="code-quote">"User ["</span> + currentUser.getPrincipal() + <span class="code-quote">"] logged in successfully."</span> ); |
| </pre> |
| </div> |
| </div> |
| |
| <p>We can also test to see if they have specific role or not:</p> |
| |
| <p></p> |
| |
| <div class="code panel" style="border-width: 1px;"> |
| <div class="codeContent panelContent"> |
| <pre class="code-java"> |
| <span class="code-keyword">if</span> ( currentUser.hasRole( <span class="code-quote">"schwartz"</span> ) ) { |
| log.info(<span class="code-quote">"May the Schwartz be with you!"</span> ); |
| } <span class="code-keyword">else</span> { |
| log.info( <span class="code-quote">"Hello, mere mortal."</span> ); |
| } |
| </pre> |
| </div> |
| </div> |
| |
| <p>We can also see if they have a permission to act on a certain type of entity:</p> |
| |
| <p></p> |
| |
| <div class="code panel" style="border-width: 1px;"> |
| <div class="codeContent panelContent"> |
| <pre class="code-java"> |
| <span class="code-keyword">if</span> ( currentUser.isPermitted( <span class="code-quote">"lightsaber:weild"</span> ) ) { |
| log.info(<span class="code-quote">"You may use a lightsaber ring. Use it wisely."</span>); |
| } <span class="code-keyword">else</span> { |
| log.info(<span class="code-quote">"Sorry, lightsaber rings are <span class="code-keyword">for</span> schwartz masters only."</span>); |
| } |
| </pre> |
| </div> |
| </div> |
| |
| <p>Also, we can perform an extremely powerful <em>instance-level</em> permission check - the ability to see if the user |
| has the ability to access a specific instance of a type:</p> |
| |
| <p></p> |
| |
| <div class="code panel" style="border-width: 1px;"> |
| <div class="codeContent panelContent"> |
| <pre class="code-java"> |
| <span class="code-keyword">if</span> ( currentUser.isPermitted( <span class="code-quote">"winnebago:drive:eagle5"</span> ) ) { |
| log.info(<span |
| class="code-quote">"You are permitted to 'drive' the 'winnebago' with license plate (id) 'eagle5'. "</span> + |
| <span class="code-quote">"Here are the keys - have fun!"</span>); |
| } <span class="code-keyword">else</span> { |
| log.info(<span class="code-quote">"Sorry, you aren't allowed to drive the 'eagle5' winnebago!"</span>); |
| } |
| </pre> |
| </div> |
| </div> |
| |
| <p>Piece of cake, right?</p> |
| |
| <p>Finally, when the user is done using the application, they can log out:</p> |
| |
| <p></p> |
| |
| <div class="code panel" style="border-width: 1px;"> |
| <div class="codeContent panelContent"> |
| <pre class="code-java"> |
| currentUser.logout(); <span class="code-comment">//removes all identifying information and invalidates their session too.</span> |
| </pre> |
| </div> |
| </div> |
| |
| <p>Well, that's the core to using Apache Shiro at the application-developer level. And although there is some pretty |
| sophisticated stuff going on under the hood to make this work so elegantly, that's really all there is to it.</p> |
| |
| <p>But you might ask yourself, "But who is responsible for getting the user data during a login (usernames and |
| passwords, role and permissions, etc), and who actually performs those security checks during runtime?" Well, you |
| do, by implementing what Shiro calls a <a href="realm.html" title="Realm">Realm</a> and plugging that <tt>Realm</tt> |
| into Shiro's configuration. </p> |
| |
| <p>However, how you configure a <a href="realm.html" title="Realm">Realm</a> is largely dependent upon your runtime |
| environment. For example, if you run a standalone application, or if you have a web based application, or a Spring |
| or JEE container-based application, or combination thereof. That type of configuration is outside the scope of this |
| QuickStart, since its aim is to get you comfortable with the API and Shiro's concepts.</p> |
| |
| <p>When you're ready to jump in with a little more detail, you'll definitely want to read the <a |
| href="java-authentication-guide.html" title="Java Authentication Guide">Authentication Guide</a> and <a |
| href="java-authorization-guide.html" title="Java Authorization Guide">Authorization Guide</a>. Then can move |
| onto other <a href="documentation.html" title="Documentation">Documentation</a>, in particularly the <a |
| href="reference.html" title="Reference">Reference Manual</a>, to answer any other questions. You'll also |
| probably want to join the user <a href="mailing-lists.html" title="Mailing Lists">mailing list</a> - you'll find |
| that we have a great community with people willing to help whenever possible.</p> |
| |
| <p>Thanks for following along. We hope you enjoy using Apache Shiro!</p> |