An Introduction to Shiro (formerly JSecurity) – A Beginner’s Tutorial Part 1
Introduction
NOTE: Updated in January 2011.
I recently took over a project that used Apache Shiro for web application security. Shiro was previously known as JSecurity (and briefly also called Ki). Not having used Shiro before, I needed to do some research and learn the basics. This blog entry is designed to assist other developers in applying Shiro to a web application. Please understand that I'm just a beginner in using Shiro. Any mistakes in my explanations or code are my responsibility. If you do notice that something is wrong, please post a comment.
From the Shiro web site:
Apache Shiro is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management.
(http://shiro.apache.org - accessed January 2011)
In March 2009, JSecurity's developers changed the JSecurity name to Ki and then to Shiro for various reasons. So you may hear/read about reference to all three names. According to the Apache Software Foundation: "Ki entered the Apache Incubator in June, 2008" (http://incubator.apache.org/projects/ki.html, accessed on April 5, 2009). In September 2010, Shiro became a Apache Top Level Project. The current release (January 2011) of Shiro is 1.1.0.
Shiro provides powerful capabilities with minimal setup--if you're able to use Shiro's configuration defaults in your project. But even if you're not able to use the defaults, you can provide your configuration to Shiro or you can extend one or more of the Shiro classes to customize how it works.
Tutorial Description and Setup
Part 1 of this tutorial starts with a basic web application that has no security. You can download an archived Eclipse dynamic web project here. The project uses Maven to manage dependencies. If you're not familiar with Maven, see the references below. Eclipse has an excellent Maven plugin (see: http://www.sonatype.com/books/m2eclipse-book/reference/index.html ). You should be able to import the archived project directly into Eclipse. The project's name is nosecurity. If you don't use Eclipse, just unzip the downloaded file (nosecurity_mvn.zip) and copy the source code to your own Java IDE.
You must also download the separate Apache Derby database as I'm going to show you how to use Shiro when your web application is storing usernames and passwords in a database. Note that Shiro comes with support for many other kinds of storage mechanisms. Unzip this download into c:/derby on your computer.
To use the Derby database with Tomcat and connection pooling you'll need to download the Derby lib files at http://db.apache.org/derby/releases/release-10.4.2.0.html. After unzipping the download copy the derby.jar to your Tomcat's /lib folder. The nosecurity web application uses connection pooling to manage connections to the Derby database. For Tomcat to find the correct driver class to connect to Derby the derby jar file must be in Tomcat's lib directory.
The no security web application includes an index.jsp page and a separate folder (named secure) that has two web pages (users.jsp and index.jsp). The pages under the secure folder are supposed to be available only to logged in (authenticated) users. Under the src/main/java folder are packages with the data access, model, and Servlet classes.
Testing The Database Connection
After you've got everything setup you can test the application's connection to Derby by running the TestConnectionFactory class that is in the dao package. This class is just a standard Java class with a main method. In the main method, it uses the ConnectionFactory class to get a connection to the Derby database, then displays some information about Derby, and shows the results of querying the users table. The users table is where the project is storing the usernames and passwords for the tutorial. Note if you did not unzip the Derby database (securityDB) into c:/derby you will need to change the parth to securityDB in class ConnectionFactory, method getConnection, in the context.xml file under the META-INF folder, and in jetty-env.xml in WEB-INF folder.
Running The Tutorial
After confirming that the project can connect to the Derby database, you can build and deploy the web application to a Java Servlet container and web server such as Tomcat or Jetty. The tutorial was tested on Tomcat version 6 and Jetty. Remember if you're using Eclipse, you'll need the Maven Eclipse plugin so that all the dependent jars will be provided to the project. See the reference below for how to get the Maven Eclipse plugin.
You can also use the Maven jetty plugin (see reference below for how to install Maven if you've don't already have Maven) to run the web application if you're not using Eclipse and Tomcat. Just open a command window and navigate to where you unzipped the nosecurity_mvn.zip download. Make sure you're in the nosecurity directory. Then do the following (in this example I unzipped nosecurity_mvn.zip to c:\jsecurity_examples):
c:\jsecurity_examples\nosecurity\mvn clean
c:\jsecurity_examples\nosecurity\mvn jetty:run
Once you see [INFO] Started Jetty Server in the command window, open your web browser and go to this URL: http://localhost:8080/nosecurity/. You should see the contents of the index.jsp. To stop the Jetty server type control-c in the command window.
Since this web application has no security you should be able to click on all the links and all the web pages should display, including the secure/users.jsp which displays the records from the users table that is the Derby database.
What's Next?
I realize this seems like a lot of setup just to get a simple web application to run. But I want to ensure that you can run this web application that uses a Derby database to store user information. In future tutorials, I'll be adding to this web application features from Shiro to enable security. So it's important that you get the basic web application working correctly in your development environment so that if you run into problems in the future tutorials you'll be able to more easily determine the cause.
In part 2 of this tutorial, I'll add basic security using Shiro to the web application to prevent users who have not logged in from viewing the pages in the secure folder.
References
- No Security Example Application, /jsecurity_examples/nosecurity_mvn.zip
- Apache Shiro http://shiro.apache.org/
- Apache Shiro API, http://shiro.apache.org/static/current/apidocs/
- Apache Shiro Mailing Lists, http://shiro.apache.org/mailing-lists.html
- Apache Derby, http://db.apache.org/derby/
- Apache Tomcat, http://tomcat.apache.org/
- Jetty, http://jetty.mortbay.org/jetty5/index.html
- Maven: The Definitive Guide, http://www.sonatype.com/books/maven-book/reference/public-book.html
- Developing with Eclipse and Maven, http://www.sonatype.com/books/m2eclipse-book/reference/index.html
I am working on implemneting Shiro and was looking at your tutorial. I may be missing something but when I run the TestConnectionFactory I get an exception stating that the USERS schema does not exist.
I connected to the DB supplied and noticed that this is correct - the USERS schema doesn't exist. I did unzip securityDB to c:\derby as instructed.
Any possiblility the uploaded data did not contain this table?
This line in class ConnectionFactory:
String sourceURL = "jdbc:derby:/derby/" + dbName + ";create=true";
needs to be changed to
String sourceURL = "jdbc:derby:c:/derby/" + dbName + ";create=true";
if you are running this on a Windows computer and have copied the no security database to c:/derby.
When I first built this example app I was on Windows, but when I updated two years later I was on a Mac.
Let me know if that fixes your issue.
It's working fine now and I'm moving on to part two.
Thanks Again.
Keith
I am a new comer in the programming world,When I first built this example app I also made mistake like this friend--Keith,I spent half-hour to find and fixed it ,and just because the "String sourceURL" is not the correct path.Then,I think you should draw a red line in the sentence “you will need to change the parth to securityDB in class ConnectionFactory, method getConnection, in the context.xml file under the META-INF folder, and in jetty-env.xml in WEB-INF folder.”, in order to avoid the newcomers like me to make the same mistake.
Thanks.
On windows,I have added "c:" into the path in "method getConnection", "context.xml under META-INF folder", "jetty-env.xml in WEB-INF folder".
When I run TestConnectionFactory.java, which throw the excetion "java.sql.SQLSyntaxErrorException: Schema 'USERS' does not exist"
I think that may lost some step to setup the data into derby database!
Can you help me?
I've changed the line :
"jdbc:derby:/derby/" + dbName + ";create=true"
to:
"jdbc:derby:c:/derby/" + dbName + ";create=true"
on a Windows,but when i debug this application on a eclipse,and i found that the connection object was still print the "jdbc:derby:/derby/" one?
I can't find what wrong with that, can you help me?
<New id="security" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg><Ref id="wac"/></Arg>
<Arg>jdbc/security</Arg>
<Arg>
<New class="org.apache.commons.dbcp.BasicDataSource">
<Set name="driverClassName">org.apache.derby.jdbc.EmbeddedDriver</Set>
<Set name="url">jdbc:derby:/Unix or Mac location/securityDB;create=false</Set>
<Set name="username">users</Set>
<Set name="password">password</Set>
</New>
</Arg>
</New>
</Configure>
Based on the latest version of Jetty Server (as of 2013), i have to change the package of jetty to have org.eclipse for WebAppContext as well as Resource. Used Configure id in Ref id as per some other reference. Also please use create=true only for tutorial 1 and rest all other 2,3 and 4th tutorials should say create=false.
Similarly modify the changes in ConnectionFactory.java.
regards,
raj