0

How to implement single sign on(SSO) using Apache Shiro on zk

asked 2015-11-03 16:17:45 +0800

ifmis gravatar image ifmis
1 2

updated 2015-11-03 16:31:50 +0800

Hello,

I am currently working on a project which uses Spring in backend and ZK on frontend and its security by Apache Shiro.

Now am in demand of implementing Single Sign On as it is composed of many modules each deployable independently. I tried to do a deep search on internet and I found some resources and articles showing how to achieve that. Unfortunately it didn't help me.

Below are the articles I used:

  1. #support.stormpath.com/hc/en-us/articles/203815036-Can-I-SSO-between-multiple-Wars-in-the-same-servlet-with-Stormpath-and-Apache-Shiro-#
  2. #shiro-user.582556.n2.nabble.com/Shiro-and-multiple-wars-within-the-same-Servlet-Container-td5560737.html#a5563334#

Below are my configurations. Please check if I am doing wrong somewhere.

I welcome any helpful suggestion.

Spring config

<beans xmlns="......">

<bean id="myRealm" class="myRealmClass">
    <property name="cachingEnabled" value="true" />
    <property name="authenticationCachingEnabled" value="true" />
    <!-- <property name="authenticationCacheName" value="authenticationCache" 
        /> -->
    <property name="authorizationCachingEnabled" value="true" />
    <!-- <property name="authorizationCacheName" value="authorizationCache" 
        /> -->
</bean>

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="sessionMode" value="native" />
    <property name="realm" ref="myRealm" />
    <property name="sessionManager" ref="sessionManager" />
    <property name="cacheManager" ref="cacheManager" />
    <property name="rememberMeManager" ref="rememberMeManager" />
</bean>

<!-- Ehcache -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
    <property name="cacheManagerConfigFile" value="classpath:ehcache.xml" />
</bean>

<bean id="sessionIdGenerator"
    class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator" />

<!-- Cookie -->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
    <constructor-arg value="sid" />
    <property name="httpOnly" value="true" />
    <property name="maxAge" value="180000" />
</bean>

<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
    <constructor-arg value="rememberMe" />
    <property name="httpOnly" value="true" />
    <property name="maxAge" value="2592000" /><!-- 30天 -->
</bean>

<bean id="cookie" class="org.apache.shiro.web.servlet.SimpleCookie">
    <property name="name" value="SSOCookie" />
    <property name="path" value="/" />
    <property name="domain" value="localhost" />

</bean>

<!-- rememberMe -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
    <property name="cipherKey"
        value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}" />
    <property name="cookie" ref="rememberMeCookie" />
</bean>

<bean id="onlineSessionFactory" class="org.apache.shiro.session.mgt.SimpleSessionFactory" />

<!-- DAO -->
<bean id="sessionDAO"
    class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
    <property name="activeSessionsCacheName" value="shiro-activeSessionCache" />
    <property name="sessionIdGenerator" ref="sessionIdGenerator" />
</bean>


<bean id="sessionValidationScheduler"
    class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler">
    <property name="sessionValidationInterval" value="1800000" />
    <property name="sessionManager" ref="sessionManager" />
</bean>


<bean id="sessionManager"
    class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    <property name="globalSessionTimeout" value="1800000" />
    <property name="sessionFactory" ref="onlineSessionFactory" />
    <property name="deleteInvalidSessions" value="true" />
    <property name="sessionValidationSchedulerEnabled" value="true" />
    <property name="sessionValidationScheduler" ref="sessionValidationScheduler" />
    <property name="sessionDAO" ref="sessionDAO" />
    <property name="sessionIdCookieEnabled" value="true" />
    <property name="sessionIdCookie" ref="cookie" />
</bean>

<!-- Secure Spring remoting: Ensure any Spring Remoting method invocations -->
<!-- can be associated with a Subject for security checks. -->
<bean id="secureRemoteInvocationExecutor"
    class="org.apache.shiro.spring.remoting.SecureRemoteInvocationExecutor">
    <property name="securityManager" ref="securityManager" />
</bean>

<!-- SecurityUtils.setSecurityManager(securityManager) -->
<bean
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="staticMethod"
        value="org.apache.shiro.SecurityUtils.setSecurityManager" />
    <property name="arguments" ref="securityManager" />
</bean>

<bean id="casFilter" class="org.apache.shiro.cas.CasFilter">
    <property name="failureUrl" value="/login.zul" />
</bean>

<!-- Shiro Web -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager" />
    <property name="successUrl" value="/index.zul" />
</bean>

<!-- Shiro -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

<bean
    class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
    depends-on="lifecycleBeanPostProcessor" />
<bean
    class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <property name="securityManager" ref="securityManager" />
</bean>

</beans>

ehCache.xml

<ehcache xmlns:xsi="...." 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" timeToIdleSeconds="0" timeToLiveSeconds="0"
              overflowToDisk="true" memoryStoreEvictionPolicy="LFU">
</defaultCache>

</ehcache>

web.xml

<web-app version="3.0" xmlns=".....">

<distributable />

<!-- SHIRO -->
<!-- <listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> 
    </listener> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class> 
    </filter> -->


<!-- The filter-name matches name of a 'shiroFilter' bean inside applicationContext.xml -->
<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>

<!-- ensure that Shiro works in subsequent filters in the filter chain: -->
<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

<filter>
    <filter-name>encoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<!-- spring-orm-hibernate4的OpenSessionInViewFilter -->
<filter>
    <filter-name>opensessioninview</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>opensessioninview</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/application-context.xml, /WEB-INF/shiro-context.xml </param-value>
</context-param>

<!-- Loads the Spring web application context -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- RequestContextHolder.currentRequestAttributes() -->
<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

<!-- ZK -->
<listener>
    <description>ZK listener for session cleanup</description>
    <listener-class>org.zkoss.zk.ui.http.HttpSessionListener</listener-class>
</listener>

<servlet>
    <description>ZK loader for ZUML pages</description>
    <servlet-name>zkLoader</servlet-name>
    <servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>

    <!-- Must. Specifies URI of the update engine (DHtmlUpdateServlet). It 
        must be the same as <url-pattern> for the update engine. -->
    <init-param>
        <param-name>update-uri</param-name>
        <param-value>/zkau</param-value>
    </init-param>


    <load-on-startup>1</load-on-startup><!-- Must -->
    <async-supported>true</async-supported>
</servlet>
<servlet-mapping>
    <servlet-name>zkLoader</servlet-name>
    <url-pattern>*.zul</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>zkLoader</servlet-name>
    <url-pattern>*.zhtml</url-pattern>
</servlet-mapping>

<servlet>
    <description>The asynchronous update engine for ZK</description>
    <servlet-name>auEngine</servlet-name>
    <servlet-class>org.zkoss.zk.au.http.DHtmlUpdateServlet</servlet-class>


    <load-on-startup>1</load-on-startup><!-- Must -->
    <async-supported>true</async-supported>
</servlet>
<servlet-mapping>
    <servlet-name>auEngine</servlet-name>
    <url-pattern>/zkau/*</url-pattern>
</servlet-mapping>


<welcome-file-list>
    <welcome-file>login.zul</welcome-file>
</welcome-file-list>

</web-app>

With kind regards,

Emma

delete flag offensive retag edit

Comments

Even I switched to .INI configuration but still I am getting this error: [Replication Thread] ERROR o.z.i.serializable - Unable to serialize entry: $composer$=org.zkoss.bind.BindComposer@7cbb3b40 18:35:28.815 [Replication Thread] WARN n.s.e.d.RMIAsynchronousCacheReplicator - Unable to send messag

ifmis ( 2015-11-03 16:39:40 +0800 )edit

e to remote peer. Message was: error marshalling arguments; nested exception is: java.io.NotSerializableException: org.apache.shiro.web.subject.support.WebDelegatingSubject java.rmi.MarshalException: error marshalling arguments; nested exception is: java.io.NotSerializableException: org.apache.

ifmis ( 2015-11-03 16:41:34 +0800 )edit
Be the first one to answer this question!
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow
1 follower

RSS

Stats

Asked: 2015-11-03 16:17:45 +0800

Seen: 32 times

Last updated: Nov 03 '15

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More