User Authentication with Apache Shiro, Tomcat and AWS RDS MariaDB ☁

1. Overview

There are many use cases where you want to have a stand-alone Apache Shiro user authentication running with a Tomcat Server. The user authentication data can be stored in a relational database like MariaDB and accessed by Apache Shiro like during a login request.

In this post we show how to combine Apache Shiro with user authentication data stored on AWS.

2. Set up AWS RDS with MariaDB

First we want to set up a AWS RDS instance with MariaDB engine. Therefore, we navigate in the AWS console to “RDS” and then look for “Launch DB instance”.

2.1. Why MariaDB and not MySQL?

One of the biggest advantages of using MariaDB instead of MySQL is the thread-pooling ability. This makes it more robust in heavy access situations. Moreover, MariaDB is more open(-source) than MySQL regarding its development and is gaining more popularity.

2.2. Launching a MariaDB instance in AWS

After clicking “Launch DB instance” we select “Production” as use case. In the next step we can choose a T2 Micro as instance class and enter the DB instance identifier and custom master user name (“YOURUSERNAME” & “YOURPASSWORD“) credentials. In the final configuration step we select the VPC and the security group. The security group hast to allow all inbound traffic.

Lastly, we can enter a database name (“YOURDATABASENAME“) in order to automatically create a corresponing database. Everything else can be left as default. After it has been successfully created we obtain our endpoint (“YOURHOSTNAME“) under the instance where it says “Endpoint”. We also assume that the port was left as default 3306.

3. Configure Apache Shiro in Tomcat

After we set up the AWS side of our project, next is our server configuration. We want to make the database resource connection available and set up the authentication real binding in the shiro configuration.

3.1. JDBC Database connection in context.xml

Defining resources in context.xml of a Tomcat app is an elegant way to access a MariaDB later in our code and via third-party add-ins like Apache shiro. Note our resource name “jdbc/TestDB”. Edit YOURHOSTNAME, YOURDATABASENAME, YOURUSERNAME and YOURPASSWORD according to you previously chosen values.

	[main]
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/YOURDEPLOYMENTPATH">
  <!-- maxTotal: Maximum number of database connections in pool. Make sure you
         configure your mysqld max_connections large enough to handle
         all of your db connections. Set to -1 for no limit.
         -->
  <!-- maxIdle: Maximum number of idle database connections to retain in pool.
         Set to -1 for no limit.  See also the DBCP documentation on this
         and the minEvictableIdleTimeMillis configuration parameter.
         -->
  <!-- maxWaitMillis: Maximum time to wait for a database connection to become available
         in ms, in this example 10 seconds. An Exception is thrown if
         this timeout is exceeded.  Set to -1 to wait indefinitely.
         -->
  <!-- username and password: MySQL username and password for database connections  -->
  <!-- driverClassName: Class name for the old mm.mysql JDBC driver is
         org.gjt.mm.mysql.Driver - we recommend using Connector/J though.
         Class name for the official MySQL Connector/J driver is com.mysql.jdbc.Driver.
         -->
  <!-- url: The JDBC connection url for connecting to your MySQL database.
         -->
  <Resource auth="Container" driverClassName="org.mariadb.jdbc.Driver" factory="org.apache.commons.dbcp2.BasicDataSourceFactory" maxIdle="30" maxTotal="100" maxWaitMillis="10000" name="jdbc/TestDB" password="YOURPASSWORD" type="javax.sql.DataSource" url="jdbc:mariadb://YOURHOSTNAME.com:3306/YOURDATABASENAME" username="YOURUSERNAME"/>

</Context>

3.2. shiro.ini

Finally, what is left is the database resource binding for Apache Shiro. We do this in shiro.ini but a programmatic approach is also possible. Note we don’t have to hard code your database connection credentials and only define the database resource.

[main]
#...

ds = org.apache.shiro.jndi.JndiObjectFactory
ds.resourceName = java:comp/env/jdbc/TestDB
ds.requiredType = javax.sql.DataSource

#alternative to context.xml provided resource:
#ds = org.mariadb.jdbc.MariaDbDataSource
#ds.serverName = YOURDATABASEDOMAIN
#ds.serverName = YOURDATABASEIP
#ds.user = YOURDATABASEUSERNAME
#ds.password = YOURDATABASEPASSWORD
#ds.databaseName = YOURDATABASENAME

jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.permissionsLookupEnabled = true
#....
 

4. Conclusion

That’s it. Make sure to debug via your log output. Check if you can access your AWS database manually to exclude network problems if it is not working at once.

Also consider connecting via Amazon VPC to optimize security.

Leave a Reply

Your email address will not be published. Required fields are marked *