-
FEATURED COMPONENTS
First time here? Check out the FAQ!
1 | initial version | |
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:
Below are my configurations. Please check if I am doing wrong somewhere.
I welcome any helpful suggestion.
Spring config
<beans xmlns="......></p> <pre><code><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>="" <="" code="">
</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
2 | No.2 Revision |
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:
Below are my configurations. Please check if I am doing wrong somewhere.
I welcome any helpful suggestion.
Spring config
<beans xmlns="......></p>
<pre><code><bean id=" myrealm"="" class="myRealmClass" >="" <property="" xmlns="......">
<bean id="myRealm" class="myRealmClass">
<property name="cachingEnabled" value="true" >="" <property="" />
<property name="authenticationCachingEnabled" value="true" >="" <!--="" <property="" />
<!-- <property name="authenticationCacheName" value="authenticationCache" >="" -->="" <property=""
/> -->
<property name="authorizationCachingEnabled" value="true" >="" <!--="" <property="" />
<!-- <property name="authorizationCacheName" value="authorizationCache" >="" -->="" <="" bean>="" <bean=""
/> -->
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" >="" <property="" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="sessionMode" value="native" >="" <property="" />
<property name="realm" ref="myRealm" >="" <property="" />
<property name="sessionManager" ref="sessionManager" >="" <property="" />
<property name="cacheManager" ref="cacheManager" >="" <property="" />
<property name="rememberMeManager" ref="rememberMeManager" >="" <="" bean>="" <!--="" ehcache="" -->="" <bean="" />
</bean>
<!-- Ehcache -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager" >="" <property="" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml" >="" <="" bean>="" <bean="" id="sessionIdGenerator" />
</bean>
<bean id="sessionIdGenerator"
class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator" >="" <!--="" cookie="" -->="" <bean="" />
<!-- Cookie -->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie" >="" <constructor-arg="" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="sid" >="" <property="" />
<property name="httpOnly" value="true" >="" <property="" />
<property name="maxAge" value="180000" >="" <="" bean>="" <bean="" />
</bean>
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie" >="" <constructor-arg="" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="rememberMe" >="" <property="" />
<property name="httpOnly" value="true" >="" <property="" />
<property name="maxAge" value="2592000" ><!--="" 30天="" -->="" <="" bean>="" <bean="" /><!-- 30天 -->
</bean>
<bean id="cookie" class="org.apache.shiro.web.servlet.SimpleCookie" >="" <property="" class="org.apache.shiro.web.servlet.SimpleCookie">
<property name="name" value="SSOCookie" >="" <property="" />
<property name="path" value="/" >="" <property="" />
<property name="domain" value="localhost" >="" <="" bean>="" <!--="" rememberme="" -->="" <bean="" />
</bean>
<!-- rememberMe -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager" >="" <property="" name="cipherKey" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cipherKey"
value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}" >="" <property="" />
<property name="cookie" ref="rememberMeCookie" >="" <="" bean>="" <bean="" />
</bean>
<bean id="onlineSessionFactory" class="org.apache.shiro.session.mgt.SimpleSessionFactory" >="" <!--="" dao="" -->="" <bean="" id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO" >="" <property="" />
<!-- DAO -->
<bean id="sessionDAO"
class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
<property name="activeSessionsCacheName" value="shiro-activeSessionCache" >="" <property="" />
<property name="sessionIdGenerator" ref="sessionIdGenerator" >="" <="" bean>="" <bean="" id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler" >="" <property="" />
</bean>
<bean id="sessionValidationScheduler"
class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler">
<property name="sessionValidationInterval" value="1800000" >="" <property="" />
<property name="sessionManager" ref="sessionManager" >="" <="" bean>="" <bean="" id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager" >="" <property="" />
</bean>
<bean id="sessionManager"
class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<property name="globalSessionTimeout" value="1800000" >="" <property="" />
<property name="sessionFactory" ref="onlineSessionFactory" >="" <property="" />
<property name="deleteInvalidSessions" value="true" >="" <property="" />
<property name="sessionValidationSchedulerEnabled" value="true" >="" <property="" />
<property name="sessionValidationScheduler" ref="sessionValidationScheduler" >="" <property="" />
<property name="sessionDAO" ref="sessionDAO" >="" <property="" />
<property name="sessionIdCookieEnabled" value="true" >="" <property="" />
<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="" />
</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" />
</bean>
<!-- SecurityUtils.setSecurityManager(securityManager) -->
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod"
value="org.apache.shiro.SecurityUtils.setSecurityManager" >="" <property="" />
<property name="arguments" ref="securityManager" >="" <="" bean>="" <bean="" />
</bean>
<bean id="casFilter" class="org.apache.shiro.cas.CasFilter" >="" <property="" class="org.apache.shiro.cas.CasFilter">
<property name="failureUrl" value="/login.zul" >="" <="" bean>="" <!--="" shiro="" web="" -->="" <bean="" />
</bean>
<!-- Shiro Web -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" >="" <property="" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" >="" <property="" />
<property name="successUrl" value="/index.zul" >="" <="" bean>="" <!--="" shiro="" -->="" <bean="" />
</bean>
<!-- Shiro -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" >="" <bean="" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" >="" <bean="" class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor" >="" <property="" />
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" >="" <="" bean>="" <="" code="">
/>
</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
3 | No.3 Revision |
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:
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