Search code examples
maventomcat7single-sign-onshiro

Single Sign on with Apache Shiro and Tomcat


I have two separate maven modules: One of them is a rest application, and the other a web app.

They run on the same tomcat 7 server, deployed as different wars, and use Shiro for authentication and authorization.

Since the web application needs to make ajax calls to the rest services, I thought it would be nice to add this SSO thing to both applications. So as suggested by this answer, I made the necessary changes to the modules, hoping it would be an easy task, but it wasn't to me. I can authenticate in each application separately, but cannot manage to make them share the session info. Every time I log in the web app and try to access a rest service, I'm redirected to the rest service login page, and vice-versa.

Here is the shiro.ini content for the web app:

[main]

credentialsMatcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName = SHA-256

dataSource = com.mysql.jdbc.jdbc2.optional.MysqlDataSource
dataSource.user = ****
dataSource.password = ****
dataSource.port = ****
dataSource.url = jdbc:mysql://localhost:****/****
dataSource.databaseName = ****

jdbcRealm = com.camacua.shiro.realm.SaltAwareJdbcRealm
jdbcRealm.credentialsMatcher = $credentialsMatcher
jdbcRealm.dataSource = $dataSource
jdbcRealm.permissionsLookupEnabled = true
jdbcRealm.saltStyle = COLUMN
jdbcRealm.saltedAuthenticationQuery = select password, password_salt, userId from AccountInfo where username = ?
jdbcRealm.userRolesQuery = select role_name from AccountInfo_Role where accountInfo_username = ?
jdbcRealm.permissionsQuery = select permission_name from Role_Permission where role_name = ?
securityManager.realm = $jdbcRealm

sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionManager.sessionDAO = $sessionDAO
cookie = org.apache.shiro.web.servlet.SimpleCookie
cookie.name = SSOcookie
cookie.path = /
cookie.domain = localhost
sessionManager.sessionIdCookie = $cookie
securityManager.sessionManager = $sessionManager

cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
cacheManager.cacheManagerConfigFile = classpath:ehcache.xml
securityManager.cacheManager = $cacheManager

securityManager.sessionMode = native

#Para testing:
ssl.enabled=false

shiro.loginUrl = /login.jsp

[urls]
/css/**=anon
/img/**=anon
/logout = logout
/** = ssl,authc

And the shiro.ini file for the rest app:

[main]
credentialsMatcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName = SHA-256

dataSource = com.mysql.jdbc.jdbc2.optional.MysqlDataSource
dataSource.user = ****
dataSource.password = ****
dataSource.port = ****
dataSource.url = jdbc:mysql://localhost:****/****
dataSource.databaseName = ****

jdbcRealm = com.camacua.shiro.realm.SaltAwareJdbcRealm
jdbcRealm.credentialsMatcher = $credentialsMatcher
jdbcRealm.dataSource = $dataSource
jdbcRealm.permissionsLookupEnabled = true
jdbcRealm.saltStyle = COLUMN
jdbcRealm.saltedAuthenticationQuery = select password, password_salt, userId from AccountInfo where username = ?
jdbcRealm.userRolesQuery = select role_name from AccountInfo_Role where accountInfo_username = ?
jdbcRealm.permissionsQuery = select permission_name from Role_Permission where role_name = ?
securityManager.realm = $jdbcRealm

sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionManager.sessionDAO = $sessionDAO
cookie = org.apache.shiro.web.servlet.SimpleCookie
cookie.name = SSOcookie
cookie.path = /
cookie.domain = localhost
sessionManager.sessionIdCookie = $cookie
securityManager.sessionManager = $sessionManager

cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
cacheManager.cacheManagerConfigFile = classpath:ehcache.xml
securityManager.cacheManager = $cacheManager

securityManager.sessionMode = native

#ssl.enabled=false

authc.loginUrl = /login

[urls]
/test/** = anon
/** = authc

The ehcache.xml file contains exactly what the stormpath site suggests in both projects:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
         monitoring="autodetect" dynamicConfig="true">

    <diskStore path="java.io.tmpdir" />

    <cacheManagerPeerProviderFactory
            class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
            properties="peerDiscovery=automatic,
                        multicastGroupAddress=230.0.0.1,
                        multicastGroupPort=4446, timeToLive=1"
            propertySeparator="," />

    <cacheManagerPeerListenerFactory
            class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory" />

    <cache name="shiro-activeSessionCache" maxElementsInMemory="600"
           eternal="true" overflowToDisk="true" memoryStoreEvictionPolicy="LFU">
        <cacheEventListenerFactory
                class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" />
    </cache>

    <defaultCache maxElementsInMemory="100" eternal="true"
                  overflowToDisk="true" memoryStoreEvictionPolicy="LFU">
    </defaultCache>
</ehcache>

As you can see, I'm using a custom realm, but I'm pretty sure it's working properly, since the authentication part is not giving me problems at all. any suggestion on what I'm doing wrong? Thanks in advance.

UPDATE: I just copied the web project and renamed it. Running the two web twin applications has the same effect.


Solution

  • The problem was related with the jsp pages I created. I declared variables in them with session scope. That somehow was overriding the session cookie, and losing the session id.