gwt

GWT Spring Security Example

In this example we will learn how to secure our GWT application using Spring Security. Tools and technologies used in this example are Java 1.8, Eclipse Luna 4.4.2, Eclipse GWT Plugin 2.6

1. Components

Below we will give a brief description of the components/software used in this example.

1.1 GWT

GWT is a development toolkit for building and optimizing complex browser-based applications. Its goal is to enable productive development of high-performance web applications without the developer having to be an expert in browser quirks, XMLHttpRequest, and JavaScript. GWT is used by many products at Google, including AdWords, AdSense, Flights, Hotel Finder, Offers, Wallet, Blogger. It’s open source, completely free, and used by thousands of developers around the world.

1.2 Spring Security

The Spring Framework provides a comprehensive programming and configuration model for modern Java-based enterprise applications – on any kind of deployment platform. Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements. It provides good protection against attacks like session fixation, clickjacking, cross site request forgery, etc.

1.3 Maven

Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project’s build, reporting and documentation from a central piece of information.

2. Project setup

Below is the screenshot of project setup.

Figure 1. Project Setup
Figure 1. Project Setup

3. Dependencies

Below is the list of dependencies which is required to run this example.

  • commons-logging
  • spring-aop
  • spring-asm
  • spring-beans
  • spring-context
  • spring-core
  • spring-expression
  • spring-security-config
  • spring-security-core
  • spring-security-web
  • spring-web

4. GWT configuration

Add the below code in the GWT configuration file:

<inherits name="com.gwt.ss.GwtSecurity"/>

GwtSpringSecurity.gwt.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.6.0//EN"
"http://google-web-toolkit.googlecode.com/svn/tags/2.6.0/distro-source/core/src/gwt-module.dtd">
<module rename-to='gwtspringsecurity'>

  <inherits name='com.google.gwt.user.User'/>
  <inherits name="com.gwt.ss.GwtSecurity"/>
  <inherits name='com.google.gwt.user.theme.clean.Clean'/>

  <entry-point class='com.javacodegeeks.client.GwtSpringSecurity'/>

  <source path='client'/>

  <add-linker name="xsiframe"/>
</module>

5. Custom Authentication Provider

Below is the snippet for the custom authentication provider class.

CustomAuthenticationProvider.java

package com.javacodegeeks.server;

import java.util.HashMap;
import java.util.Map;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

public class CustomAuthenticationProvider implements AuthenticationProvider {

  private static Map<String, String> users = new HashMap<String, String>();

  static {
    users.put("mark", "MarkPassword");
    users.put("Robin", "RobinPassword");
    users.put("Dileep", "DileepPassword");
  }

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {

    String username = (String) authentication.getPrincipal();
    String password = (String) authentication.getCredentials();
    if (users.get(username) == null) {
      throw new UsernameNotFoundException("User not found");
    }
    String pass = users.get(username);
    if (!pass.equals(password)) {
      throw new BadCredentialsException("Incorrect password");
    }
    Authentication customAuthentication = new CustomUserAuthentication("ROLE_USER", authentication);
    customAuthentication.setAuthenticated(true);
    return customAuthentication;
  }

  @Override
  public boolean supports(Class<? extends Object> authentication) {
    return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
  }
}

This class implements the org.springframework.security.authentication.AuthenticationProvider. This indicates a class can process a specific Authentication implementation. The authenticate() method performs authentication with the same contract as AuthenticationManager.authenticate(Authentication).

6. Custom User Authentication

Below is the snippet of the custom user authentication class.

CustomUserAuthentication.java

package com.javacodegeeks.server;

import java.util.ArrayList;
import java.util.Collection;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;

public class CustomUserAuthentication implements Authentication {

  private static final long serialVersionUID = -1L;

  private boolean authenticated;
  private GrantedAuthority grantedAuthority;
  private Authentication auth;

  public CustomUserAuthentication(String role, Authentication authentication) {
    this.grantedAuthority = new GrantedAuthorityImpl(role);
    this.auth = authentication;
  }

  @Override
  public Collection<GrantedAuthority> getAuthorities() {
    Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    authorities.add(grantedAuthority);
    return authorities;
  }

  @Override
  public Object getCredentials() {
    return auth.getCredentials();
  }

  @Override
  public Object getDetails() {
    return auth.getDetails();
  }

  @Override
  public Object getPrincipal() {
    return auth.getPrincipal();
  }

  @Override
  public boolean isAuthenticated() {
    return authenticated;
  }

  @Override
  public void setAuthenticated(boolean authenticated) throws IllegalArgumentException {
    this.authenticated = authenticated;
  }

  @Override
  public String getName() {
    return this.getClass().getSimpleName();
  }
}

This class represents the token for an authentication request or for an authenticated principal once the request has been processed by the AuthenticationManager.authenticate(Authentication) method.

7. web.xml

To integrate Spring Security with GWT we need to make some changes in the web.xml. We will use the same servlet (GreetingServiceImpl) which gets generated when we create a ‘Web Application Project’. We will make some modification in the implementation though. Once the request has been authenticated, the Authentication will usually be stored in a thread-local SecurityContext managed by the SecurityContextHolder by the authentication mechanism which is being used. An explicit authentication can be achieved, without using one of Spring Security’s authentication mechanisms, by creating an Authentication instance and using the code:

SecurityContextHolder.getContext().setAuthentication(anAuthentication);

Note that unless the Authentication has the authenticated property set to true, it will still be authenticated by any security interceptor (for method or web invocations) which encounters it. In most cases, the framework transparently takes care of managing the security context and authentication objects for you.

7.1. Servlet Mapping

Below is the servlet mapping which we need to define in the web.xml

<servlet>
  <servlet-name>greetServlet</servlet-name>
  <servlet-class>com.javacodegeeks.server.GreetingServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>greetServlet</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

7.2. Filter

We also need to define a Spring security filter as below.

<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>

DelegatingFilterProxyis a proxy for a standard Servlet Filter, delegating to a Spring-managed bean that implements the Filter interface.  It supports a “targetBeanName” filter init-param in web.xml, specifying the name of the target bean in the Spring application context.

web.xml will usually contain a DelegatingFilterProxy definition, with the specified filter-name corresponding to a bean name in Spring’s root application context. All calls to the filter proxy will then be delegated to that bean in the Spring context, which is required to implement the standard Servlet Filter interface.

This approach is particularly useful for Filter implementation with complex setup needs, allowing to apply the full Spring bean definition machinery to Filter instances. Alternatively, consider standard Filter setup in combination with looking up service beans from the Spring root application context.

NOTE: The lifecycle methods defined by the Servlet Filter interface will by default not be delegated to the target bean, relying on the Spring application context to manage the lifecycle of that bean. Specifying the “targetFilterLifecycle” filter init-param as “true” will enforce invocation of the Filter.init and Filter.destroy lifecycle methods on the target bean, letting the servlet container manage the filter lifecycle.

7.3 Listener

We need to define two listeners as below.

<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
  <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

7.3.1 ContextLoaderListener

It extends org.springframework.web.context.ContextLoader and implements javax.servlet.ServletContextListener. It bootstrap listener to start up and shut down Spring’s root WebApplicationContext. It simply delegates to ContextLoader as well as to ContextCleanupListener.

7.3.2 HttpSessionEventPublisher

It implements javax.servlet.http.HttpSessionListener. It publishes HttpSessionApplicationEvents to the Spring Root WebApplicationContext. It maps javax.servlet.http.HttpSessionListener.sessionCreated() to HttpSessionCreatedEvent. Maps javax.servlet.http.HttpSessionListener.sessionDestroyed() to HttpSessionDestroyedEvent

Below is the code for web.xml.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">

  <servlet>
    <servlet-name>greetServlet</servlet-name>
    <servlet-class>com.javacodegeeks.server.GreetingServiceImpl</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>greetServlet</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

  <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>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
  </listener>

  <welcome-file-list>
    <welcome-file>GwtSpringSecurity.html</welcome-file>
  </welcome-file-list>

</web-app>

8. Spring application context

We need to define the spring application context.

<?xml version="1.0" encoding="UTF-8"?>

<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">

  <beans:bean id="customListener" class="com.javacodegeeks.server.CustomListener" />

  <http auto-config="true">
    <intercept-url pattern="/**" access="ROLE_USER" />
  </http>

  <beans:bean id="customAuthenticationProvider" class="com.javacodegeeks.server.CustomAuthenticationProvider" />

  <authentication-manager alias="authenticationManager">
    <authentication-provider ref="customAuthenticationProvider" />
  </authentication-manager>

</beans:beans>

Here we will define the Custom Authentication Listener and Authentication Provider. Spring Security 3.0 introduced the ability to use Spring EL expressions as an authorization mechanism in addition to the simple use of configuration attributes and access-decision voters. Expressions are evaluated with a root object as part of the evaluation context. Spring Security uses specific classes for web and method security as the root object, in order to provide built-in expressions and access to values such as the current principal. The base class for expression root objects is SecurityExpressionRoot. This provides some common expressions which are available in both web and method security.

The <http> tag says that we want all URLs within our application to be secured, requiring the role ROLE_USER to access them. The <http> element is the parent for all web-related namespace functionality. The <intercept-url> element defines a pattern which is matched against the URLs of incoming requests using an ant path style syntax. The access attribute defines the access requirements for requests matching the given pattern. With the default configuration, this is typically a comma-separated list of roles, one of which a user must have to be allowed to make the request. The prefix “ROLE_” is a marker which indicates that a simple comparison with the user’s authorities should be made. In other words, a normal role-based check should be used. Access-control in Spring Security is not limited to the use of simple roles (hence the use of the prefix to differentiate between different types of security attributes).

You can use multiple <intercept-url> elements to define different access requirements for different sets of URLs, but they will be evaluated in the order listed and the first match will be used. So you must put the most specific matches at the top. You can also add a method attribute to limit the match to a particular HTTP method (GET, POST, PUT etc.). If a request matches multiple patterns, the method-specific match will take precedence regardless of ordering.

Using the <authentication-provider> element means that the user information will be used by the authentication manager to process authentication requests. You can have multiple <authentication-provider> elements to define different authentication sources and each will be consulted in turn.

The <http> element is responsible for creating a FilterChainProxy and the filter beans which it uses. Common problems like incorrect filter ordering are no longer an issue as the filter positions are predefined. All authentication-provider elements must be children of the <authentication-manager> element, which creates a ProviderManager and registers the authentication providers with it

9. GWT Compile

To compile the application, right click on the project and choose Google=>GWT Compile. See the screenshot below.

Figure 2. GWT Compile
Figure 2. GWT Compile

10. Download the source file

This was an example of GWT Spring Security.

Download
You can download the full source code of this example here: GWT Spring Security

Mohammad Meraj Zia

Senior Java Developer
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button