Overview

Spring Security is an application framework that provides security services for J2EE-based enterprise software application. It is a popular and widely adopted framework, in this article we will demonstrate how to integrate it to secure a ZK application including securing pages, handling authentication process, securing components, and securing events. Our example is a simple forum-like application. Users can read, create, edit, and delete an article according to his authorities.

Configuration

Maven

We need to add dependencies for Spring Security and Maven’s transitive dependency management can include all necessary dependencies of Spring for us.

        <!-- Spring Security -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${springsecurity.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>${springsecurity.version}</version>
        </dependency>

        <!-- extra -->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2</version>
        </dependency>
  • Line 4: Becuase we use the security namespace in the application context, we need spring-security-config.
  • Line 16: Spring-core depends on commons-logging.
  • Line 21: The cglib is optional. We add it because we use CGLIB-based class proxy.
![](/zk_dev_ref/images/icon_info.png) **Note:** If you don't use Maven, please refer to Spring Security Reference Documentation to check which JAR files are needed.

Spring

Our example application also integrates Spring framework, the required configuration in web.xml is as follows:

web.xml

    <!-- Loads the Spring application context configuration -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
     <!-- For using web scoped bean -->
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

The ContextLoaderListener will load /WEB-INF/applicationContext.xml (Spring configuration file) by default, and we follow this convention so we don’t need to add extra configuration in web.xml.

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation=
    "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
    
    <context:component-scan base-package="org.zkoss.reference.developer.spring.security.model"/>

    <import resource="applicationContext-security.xml"/>
</beans>
    
  • Line 9: We can register beans by class-path scanning to reduce XML configuration effort.
  • Line 11: We can import another configuration file for Spring Security.

Security Namespace Configuration

The first configuration you should add to use Spring Security is a filter declaration in web.xml:


    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

This filter is a hook into Spring Security’s web infrastructure. It intercepts all requests and hands over them to be processed by Spring Security internal filters.

Namespace configuration has been supported by Spring framework since version 2.0 and it is an alternative configuration syntax which is closer to problem domain. It also can reduce configuration’s complexity because one element may contain multiple beans and processing steps. To use the security namespace, you should have spring-security-config in your classpath and add the schema declaration to your application context file:

applicationContext-security.xml


<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" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation=
    "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
     http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">


    <!--  HTTP configuration sample -->
    <http auto-config="true">
        <!-- ZK AU reqeust -->
        <intercept-url pattern="/zkau/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <!-- the login page -->
        <intercept-url pattern="/login.zul" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <!-- pages for anonymous access in an application -->
        <intercept-url pattern="/index.zul" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <intercept-url pattern="/articleContent.zul" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <!-- secure pages -->
        <intercept-url pattern="/**" access="ROLE_USER" />
        
        <form-login login-page="/login.zul" 
            authentication-failure-url="/login.zul?login_error=1" 
            login-processing-url="/j_spring_security_check"/>
            
        <logout logout-success-url="/index.zul" invalidate-session="true" />
    </http>     

    <!-- omit inactive configurations -->

    <authentication-manager>
        <authentication-provider user-service-ref="myUserDetailsService">
            <password-encoder hash="md5" />
        </authentication-provider>
    </authentication-manager>
    
</beans:beans>

Here we introduce some main elements and will leave the details in the subsequent sections.

  • LIne 12: The element is the parent for all web-related namespace functions and we use `auto-config` to save configuration efforts. We also create a HTTPS configuration sample in `applicationContext-security.xml`. Please see source code for details.
  • Line 32: Each Spring Security application which uses the namespace configuration must include . It is responsible for registering the `AuthenticationManager` which provides authentication services to the application.
  • Line 33:We implement our MyUserDetailsService bean to provide authentication service and configure it in element.

Secure Pages

In Spring Security, pages are protected by element under

. We can specify in `pattern` to match against the URLs of incoming requests using an ant path style syntax in element. The `access` attribute defines the access permission for requests which match the given `pattern`. Here we use simple role-based access control. In most cases, we usually secure all pages with : The "ROLE_USER" is an authority string we define and give for each authenticated user in our custom user service, `MyUserDetailsService`. Then we can selectively allow some pages for anonymous access like: `IS_AUTHENTICATED_ANONYMOUSLY` is a built-in permission value used to grant access to anonymous users **applicationContext-security.xml** ```xml ... ``` - Line 4: ZK AU requests must be available for anonymous access or ZK can't work normally. - Line 6: Remember to set login page URL available to anonymous users, otherwise users wont be able to access the log-in page (this is a common configuration error). - Line 14: Restrict all page requests with permission `ROLE_USER`. # Authentication Setting `auto-config` enables form-based login process automatically but it uses Spring Security's built-in login page. We usually build our own login page so we can specify our custom login page URL to override the default configuration. **applicationContext-security.xml** ```xml ... ``` - Line 5: Specify the URL used to render the login page at `login-page`. - Line 5: Specify the URL to redirect the browser on login failure, - Line 8: Specify the destination URL in which the user will be redirected to after logging out. In order to let Spring Security handle authentication, we should use HTML's form in a zul. **login.zul** ```xml ... User: Password: