An Introduction to Shiro (formerly JSecurity) – A Beginner’s Tutorial Part 5
Introduction
In part 4 of this series, I explained how you can use Shiro's tag library to control what is rendered in the JSPs. In part 3 of this series, I explained how you can use a users role to control access to specific parts of a web application. In this part of the series, I demonstrate how you can add another level of security to your web application by using permissions. Each role (e.g. admin, user) can have one or more permissions associated with it. Using Shiro you can restrict what someone can access based upon permission.
Using Permission to Control Access
In this example, our web application has three areas needing to be secured:
/users
/staff
/admin
Our business rules for securing each area are:
/users – user is authenticated and has role of user
/staff – user is authenticated and has role of staff or role of admin
/admin – user is authenticated and has role of admin
Since roles staff and admin both need to access the staff area, we can use permissions to control access to that area. We can assign the same permission to both the staff and admin role. We'll call that permission "secure." Any user with permission of "secure" can access the pages in the staff area. If in the future we add additional roles that need to access the staff area, we can give those new roles the "secure" permission also.
So our revised security business rules for each area are:
/users – user is authenticated and has role of user
/staff – user is authenticated and has permission of secure
/admin – user is authenticated and has role of admin
Here are our three users, their roles, and their permissions:
username |
password |
role |
permission |
bruce@hotmail.com |
bruce |
admin |
secure |
jack@hotmail.com |
jack |
staff |
secure |
sue@hotmail.com |
sue |
user |
none |
Applying our security business rules to these users we can identify who will be able to access which areas:
/user – only sue
/staff – both bruce and jack but not sue
/admin - only bruce
Example Application
You can download an example application (an archived Eclipse dynamic web project using Maven). You'll also need to download a new version of the securityDB Derby database that includes the roles_permissions table.
After downloading the securityDB Derby database, unzip it to the folder c:/derby. It's OK to overwrite the database that was there as this new version of the securityDB database should work for the previous example applications.
You can import the downloaded Eclipse archived project (named permissionsecuritywithtags) into Eclipse and then run it on a Tomcat server.
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 permissionsecuritywithtags.zip download. Make sure you're in the permissionsecuritywithtags directory. Then do the following (in this example I unzipped permissionsecuritywithtags.zip to c:\jsecurity_examples):
c:\jsecurity_examples\ permissionsecuritywithtags \mvn clean
c:\jsecurity_examples\ permissionsecuritywithtags \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/permissionsecuritywithtags/ . You should see the contents of the index.jsp. To stop the Jetty server type control-c in the command window.
Login as each user (bruce@hotmail.com, jack@hotmail.com, and sue@hotmail.com). When you're logged in as sue@hotmail.com try to go to either http://localhost:8080/permissionsecuritywithtags/staff/index.jsp or http://localhost:8080/permissionsecuritywithtags/admin/index.jsp. You should be redirected to the unauthorized web page. When you're logged in as jack@hotmail.com try to go to the http://localhost:8080/permissionsecuritywithtags/admin/index.jsp page.
Implementing Permission Security in Ki
So how do we implement security that uses permissions in Ki? By default when you attempt to authenticate a user, Ki will look for any permissions associated with the role that is associated with that user. To use Ki's default configuration you just need a table named roles_permissions with a column named role_name and a column named permission. The default permissions query is specified in class JdbcRealm, which my class RoleSecurityJdbcRealm extended. In web.xml I specified this class as the value for the JSecurityFilter's realm (a realm is a resource that Ki will use to authenticate users).
If your project cannot follow Ki's defaults, you can configure Ki to use your projects conventions (see the Ki references below).
In Servlet class LoginUser I created a Subject object and call the Subject class's login method passing it the UsernamePasswordToken object that has the user's username and password. If Ki can successfully authenticate this user by querying the users table, Ki will then query the user_roles table for roles associated with this username, and then query the roles_permissions table for permissions associated with each role_name associated with this username. All of this information will be stored in the Subject object and placed into session scope. For more information on interfaces Subject and its associated interfaces AuthenticationInfo and and AuthorizationInfo see the Ki API.
If you examine the web.xml you'll see the following statements in the configuration for the JSecurityFilter:
[filters]
roles.unauthorizedUrl = /unauthorized.jsp
perms.unauthorizedUrl = /unauthorized.jsp
#only let authenticated users
#with the appropriate role or permission
#view the web pages in the staff, user,
#and admin areas
[urls]
/staff/** = authc, perms[secure]
/admin/** = authc, roles[admin]
/user/** = authc, roles[user]
The statement perms.unauthorizedUrl = /unauthorized.jsp tells the filter to redirect people who attempt to view a web page in an area of the site for which they don't have the correct permission to the unauthorized.jsp web page.
The statement /staff/** = authc, perms[secure] means only allow people who have logged in successfully and have a permission of secure to view pages in the /staff folder.
In the Servlet LoginUser.java you'll find this statement around line number 134:
if (subject.isPermitted("secure") )
This statement uses the isPermitted method of the Subject class. This method returns true if the Subject object has the permission sent as the argument, otherwise the isPermitted method returns false.
Ki also has a tag you can use to check a user's permission. In the JSP /index.jsp I use the hasPermission tag (around line 21) to render content for only those users with the secure permission.
Summary
Ki is a comprehensive security library that gives you control over all aspects of your web application. By using permissions you can enable more specific access rules.
References
- An Introduction to Ki (formerly JSecurity) – A Beginner's Tutorial Part 4, http://www.brucephillips.name/blog/index.cfm/2009/4/5/An-Introduction-to-Ki-formerly-JSecurity--A-Beginners--Tutorial-Part-4
- An Introduction to Ki (formerly JSecurity) – A Beginner's Tutorial Part 3, http://www.brucephillips.name/blog/index.cfm/2009/4/5/An-Introduction-to-Ki-formerly-JSecurity--A-Beginners--Tutorial-Part-3
- Role Security With Tags Example Application, http://www.brucephillips.name/jsecurity_examples/rolesecuritywithtags_mvn.zip
- JSecurity, http://www.jsecurity.org/ (old web site)
- Apache Ki (new web site), http://cwiki.apache.org/confluence/display/KI/Index
- Presentation on JSecurity to the Charlotte Java Users Group, http://www.jsecurity.org/files/JSecurity.pdf
- JSecurity API 0.9.0, http://www.jsecurity.org/api/
- Ki Custom Tags, http://www.jsecurity.org/api/org/jsecurity/web/tags/package-summary.html
- Ki Custom Tags TLD, http://www.brucephillips.name/jsecurity_examples/ki%20(jsecurity)%20tld.pdf
- Using Custom Tags, J2EE Tutorial, http://java.sun.com/javaee/5/docs/tutorial/doc/bnaiy.html
- JSecurity User Mailing List, http://n2.nabble.com/JSecurity-User-f582556.html
- Apache Derby, http://db.apache.org/derby/
- Apache Tomcat, http://tomcat.apache.org/
- Jetty, http://jetty.mortbay.org/jetty5/index.html
- Apache Software Foundation, Apache incubator, http://incubator.apache.org/projects/ki.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 uploaded a new archived project with the correct artifactID in the pom.xml. You should be able to download that project, unzip, and run the mvn commands as specified in the article.
Then load the application using this URL:
http://localhost:8080/permissionsecuritywithtags/
1. changed the pom.xml to import the following dependencies:
org.apachi.key/ki-all/1.0-incubating-SNAPSHOT
org.slf4j/slf4j-simple/1.5.6
commons-beanutils/commons-beanutils/1.7.0
commons-logging/commons-logging/1.1.1
2. Changed the tag URL in the jsp pages to:
<%@ taglib prefix="jsec" uri="http://ki.apache.org/tags" %>
3. Changed the JSecurityFilter in web.xml
<filter-name>KiFilter</filter-name>
<filter-class>org.apache.ki.web.servlet.KiFilter</filter-class>
...
<filter-mapping>
<filter-name>KiFilter</filter-name>
...
4. Modified all the Java classes to use the classes from package: org.apache.ki.*
Hope this helps.