Spring Security

From Documentation

Stop.png This documentation is for an older version of ZK. For the latest one, please click here.


Spring Security 2.0 and 3.0 build on Acegi Security's solid foundations, adding many new features. The framework provides a comprehesive set of authentication and access-control services for your applications.

Running a sample application

  1. Download the war file
    zkspringsec302.war
    The tutorial sample is borrowed from Spring Security 3.0, and has been modified to work with ZK seamlessly.
  2. Deploy the war file
  • Tomcat 5.5 and above.

Copy zkspringsec302.war to the $Tomcat_Home/webapps/ folder of Tomcat server and restart Tomcat.

  1. Use your browser to visit:
    http://localhost:8080/zkspringsec302/
    username/password is rod/koala

Prerequisites of using Spring Security

To make Spring Security work with ZK properly, you have to copy the following jars to /WEB-INF/lib.

  • ZK Spring Core & Security Integration Library jar files
    • zkspring-core.jar
    • zkspring-security.jar
  • Spring Security library jar files
    • aopalliance-1.0.jar
    • aspectjweaver-1.6.8.jar
    • commons-codec-1.3.jar
    • commons-collections-3.2.jar
    • commons-lang.jar
    • commons-logging-1.1.1.jar
    • jstl-1.1.2.jar
    • log4j-1.2.14.jar
    • spring-security-acl-3.0.2.RELEASE.jar
    • spring-security-config-3.0.2.RELEASE.jar
    • spring-security-core-3.0.2.RELEASE.jar
    • spring-security-taglibs-3.0.2.RELEASE.jar
    • org.springframework.aop-3.0.2.RELEASE.jar
    • org.springframework.asm-3.0.2.RELEASE.jar
    • org.springframework.beans-3.0.2.RELEASE.jar
    • org.springframework.context-3.0.2.RELEASE.jar
    • org.springframework.context.support-3.0.2.RELEASE.jar
    • org.springframework.core-3.0.2.RELEASE.jar
    • org.springframework.expression-3.0.2.RELEASE.jar
    • org.springframework.transaction-3.0.2.RELEASE.jar
    • org.springframework.web-3.0.2.RELEASE.jar
    • org.springframework.web.servlet-3.0.2.RELEASE.jar
    • standard-1.1.2.jar

Note: Please refer to Prerequisite for using Spring Security if using ZK Spring 1.1.0 release

Configure the /WEB-INF/web.xml file

To make Tomcat work with Spring Security properly, you shall specify the location of spring-security configuration file, and define listener of spring, and filter of spring-security as follows:

 <!--
       - Location of the XML file that defines the root application context
       - Applied by ContextLoaderListener.
       -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
             ...
             /WEB-INF/applicationContext-security.xml
        </param-value>
    </context-param>

    <!--
       - Loads the root application context of this web app at startup.
       - The application context is then available via
       - WebApplicationContextUtils.getWebApplicationContext(servletContext).
       -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>    
<!--
       - Spring Security Filter Chains
       -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

Create /WEB-INF/applicationContext-security.xml

Create application-security.xml file under $myApp/WEB-INF/. This file include required configuration of spring-security.

<!--
   - Spring namespace-based configuration
   -->
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
                        
     <!--
       - Enable the @Secured annotation to secure service layer methods
       -->                   
	<global-method-security secured-annotations="enabled">
	</global-method-security>

    <!--
       - Secure the page per the URL pattern
       -->
    <http auto-config="true">
        <intercept-url pattern="/secure/extreme/**" access="ROLE_SUPERVISOR"/>
        <intercept-url pattern="/secure/**" access="IS_AUTHENTICATED_REMEMBERED" />
        <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <!-- use own login page rather than the default one -->
        <form-login login-page="/login.zul" authentication-failure-url="/login.zul?login_error=1"/>
        
        <!-- Following is list of ZK Spring Security custom filters. 
        	They needs to be exactly in the same order as shown below in order to work.  -->
        <custom-filter ref="zkDesktopReuseFilter" position="FIRST" />
        <custom-filter ref="zkDisableSessionInvalidateFilter" before="FORM_LOGIN_FILTER"/>
        <custom-filter ref="zkEnableSessionInvalidateFilter" before="FILTER_SECURITY_INTERCEPTOR"/>
        <custom-filter ref="zkLoginOKFilter" after="FILTER_SECURITY_INTERCEPTOR"/>
        <custom-filter ref="zkError403Filter" after="LOGOUT_FILTER"/>
   </http>

    <!--
    Usernames/Passwords are
        rod/koala
        dianne/emu
        scott/wombat
        peter/opal
    -->
    <authentication-manager>
    <authentication-provider>
        <password-encoder hash="md5"/>
        <user-service>
            <user name="rod" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
	        <user name="dianne" password="65d15fe9156f9c4bbffd98085992a44e" authorities="ROLE_USER,ROLE_TELLER" />
            <user name="scott" password="2b58af6dddbd072ed27ffc86725d7d3a" authorities="ROLE_USER" />
            <user name="peter" password="22b5c9accc6e1ba628cedc63a72d57f8" authorities="ROLE_USER" />
	    </user-service>
	</authentication-provider>
	</authentication-manager>
	
</beans:beans>

Notice that here only zkspring-security.xsd is referenced in the namespace declaration. In case your application needs ZK Spring core support please include zkspring-core.xsd as well. For Zk Spring 1.1.0 release namespace configuration refer to Create /WEB-INF/applicationContext-security.xml under ZK Spring 1.1.0 Release configuration details section.

Define which service to be secured

Use Spring Security annotation @Secured to protect the calling of a business service as follows:

 public interface BankService {
     
     @Secured("IS_AUTHENTICATED_ANONYMOUSLY")
     public Account readAccount(Long id);
         
     @Secured("IS_AUTHENTICATED_ANONYMOUSLY")
    public Account[] findAccounts();
     
     @Secured("ROLE_TELLER")
     public Account post(Account account, double amount);
 }

Define which ZK event to be secured

In /WEB-INF/applicationContext-security.xml, define required configurations of the namespace of zk, and specify which ZK event to secure as follows,

<!--
   - Spring namespace-based configuration
   -->
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:zksp="http://www.zkoss.org/2008/zkspring/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
						http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
                        http://www.zkoss.org/2008/zkspring/security http://www.zkoss.org/2008/zkspring/security/zkspring-security.xsd">


    <http ...>
         ...
    </http>
     ...      

<!--
 - Secure the ZK event processing per the event name and ZK component path pattern
 -->
<zksp:zk-event login-template-close-delay="5">
<zksp:intercept-event event="onClick" path="//**/btn_*" access="ROLE_TELLER"/>
<zksp:intercept-event path="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
</zksp:zk-event>

</beans:beans>
  • xmlns:zksp="http://www.zkoss.org/2008/zkspring/security tells the Spring Security engine that we will use the ZK Spring Security namespace configuration and define the name space to zksp.
  • http://www.zkoss.org/2008/zkspring/security http://www.zkoss.org/2008/zkspring/security/zkspring-security.xsd tells the Spring Security engine where to find such ZK Spring Security namespace configuration schema.
  • <zksp:zk-event> tells the Spring Security engine we want to secure ZK event processing. This will configure the necessary listeners , filters, and Spring beans automatically. In this example, login-template-close-delay="5" tells ZK to CLOSE the login window automatically in five(5) seconds if login successfully; zero(0) means close the login window immediately; and a negative value means wait for users operation.
  • <zksp:intercept-event event="onClick" path="//**/btn_*" access="ROLE_TELLER"/> tells the Spring Security engine which ZK event and components we want to secure. In this example, it says that any onClick event that is fired to the ZK components whose id starts with btn_ will be checked against the ROLE_TELLER authority.
  • <zksp:intercept-event path="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/> tells that all anonymous users can access to all events and all components.

Note: For Zk Spring 1.1.0 configuration please refer to Define which ZK event to be secured section under ZK Spring release 1.1.0 configuration details

The ZUML Page

In the following example, ZK prompts end user to login when he/she attempts to change the balance of account since the onClick event of Button component has been secured by Spring-Security.

<?variable-resolver class="org.zkoss.spring.DelegatingVariableResolver"?>
<zk>
<window title="Accouts" border="normal" width="500px">
    <zscript><![CDATA[
        void adjBalance(Button btn) {
            double bal = Double.parseDouble((String)btn.getAttribute("bal"));
            //get the account object
            bigbank.Account a = bankService.readAccount(btn.getAttribute("aid"));
            //change the account balance
            bankService.post(a, bal);
            //update the account balance on the browser
            btn.getFellow("bal_"+a.getId()).setValue(""+a.getBalance());
        }
     ]]>
    </zscript>
    <grid>
        <rows>
            <row forEach="${accounts}">
                <label value="${each.id}"/>
                <label value="${each.holder}"/>
                <label id="bal_${each.id}" value="${each.balance}"/>
                <button id="btn_m20_${each.id}" label="-$20" onClick="adjBalance(self)">
                    <custom-attributes aid="${each.id}" bal="-20"/>
                </button> 
                <button id="btn_m5_${each.id}" label="-$5" onClick="adjBalance(self)"> 
                    <custom-attributes aid="${each.id}" bal="-5"/>
                </button> 
                 ...................
            </row>
        </rows>
    </grid>
</window>
<button label="Home" href="/index.zul"/>
<button label="Logout" href="/j_spring_security_logout"/>
</zk>


Last Update : 2022/01/19

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.