Hi,

A simple post about a problem that I encountred during the development of a personnal GWT application with Spring Security and its deployment on Google Cloud GAE.

1. Creation of application and securization with Spring security

  • Create a simple GWT application by creating a “Web Application Project” in Eclipse named huojavagwtgaespringsecurity1;
  • Add the following jars in the folder huojavagwtgaespringsecurity1\war\WEB-INF\lib:
    • aopalliance-1.0.jar
    • asm.jar
    • aspectjrt-1.6.8.jar
    • aspectjweaver-1.6.8.jar
    • cglib-2.2.2.jar
    • commons-logging-1.1.1.jar
    • javassist-3.4.ga.jar
    • jstl-1.2.jar
    • spring-security-config-3.0.5.RELEASE.jar
    • spring-security-core-3.0.5.RELEASE.jar
    • spring-security-web-3.0.5.RELEASE.jar
    • spring-aop-3.0.3.RELEASE.jar
    • spring-asm-3.0.5.RELEASE.jar
    • spring-beans-3.0.5.RELEASE.jar
    • spring-context-support-3.0.5.RELEASE.jar
    • spring-context-3.0.5.RELEASE.jar
    • spring-core-3.0.5.RELEASE.jar
    • spring-expression-3.0.5.RELEASE.jar
    • spring-tx-3.0.3.RELEASE.jar
    • spring-web-3.0.5.RELEASE.jar
    • spring-webmvc-3.0.5.RELEASE.jar

  • Edit the web descriptor file web.xml, in order to add a section concerning the Spring security configuration (http filter):
    	<!-- ##################################### -->
    	<!-- SPRING SECURITY -->
    	<!-- ##################################### -->
    	<!-- Spring Security commence par la déclaration d’un filtre de servlet 
    	Cette configuration redirige l’ensemble des requêtes HTTP vers Spring Security.
    	 -->
     	<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>
    	<!-- Chargement du context Spring au démarrage -->
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>
    			/WEB-INF/spring-security.xml
    		</param-value>
    	</context-param>
    

  • Add the security access configuration file name spring-security.xml in the folder huojavagwtgaespringsecurity1\war\WEB-INF:
    <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.3.xsd">
    
    
    	<!-- ################### SPRING SECURITY ################### -->
    	<http auto-config="true">
    		<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
    		<intercept-url pattern="/**" access="ROLE_USER" /> 
    		<http-basic />
    	</http>
    
    
    	<!-- Définition d'un annuaire d’utilisateurs -->
    	<authentication-manager alias="authentication-managerHUO">
    		<authentication-provider>
    			<password-encoder hash="md5" />  <!-- Spring Security password hashing  -->
    			<user-service>
    				<user name="admin" password="ecdd6137ff6c643f5684a9b042459cb1" authorities="ROLE_ADMIN,ROLE_USER" /><!-- mdp4admin -->
    				<user name="tudu" password="58ddf6c889bdc402f5a5975178067f41" authorities="ROLE_USER" /> <!-- mdp4tudu -->
    				<user name="guest" password="7d0b460aeb13cab9951d7ded97b50fc5" authorities="ROLE_NONE" /> <!-- mdp4guest -->
    			</user-service>
    		</authentication-provider>
    	</authentication-manager>
    
    </beans:beans>
    

    Some explanations:

    • The HTTP basic authentication is used via Spring Security; We could have used a customized authentication form by changing the basic-login tag to form-login tag, by creating cutomized form pages…etc;
    • The syntax used in the acess rules /** is named/called “Ant syntax”;
    • We have defined 3 roles: ROLE_ADMIN, ROLE_USER and ROLE_NONE;
    • For the authorization of URLs, an authenticated user with the role ROLE_ADMIN can access to the URL /admin/**; every user must have the role ROLE_USER to view any others URLs /**;
    • For the user authentication, we have also defined 3 users/password (ROLES): admin/mdp4admin ROLE_ADMIN,ROLE_USER), tudu/mdp4tudu (ROLE_USER) and guest/mdp4guest (ROLE_NONE);
    • We have used the MD5 hashing algorithm in Spring Security; For MD5 conversion and MD5 reverse lookup, go to http://md5.gromweb.com/. The Supported hashing algorithms in Spring Security are plaintext, sha, sha-256, md5, md4.

  • Edit the Google App Engine (GEA) file configuration appengine-web.xml and add the following tag in order to enable HTTP sessions:
    <sessions-enabled>true</sessions-enabled>
    



2. Deployment on Jetty server

  • At this stage, we can compile our application and deploy it on GWT embedded server named Jetty. To deploy an application in HOSTED mode (DEVELOPMENT mode) on the server JETTY embedded in GWT framework see the post
    GWT/GAE: Deployment an application on GWT embedded server named Jetty in Hosted mode.
  • Open the URL http://localhost:8888/Huojavagwtgaespringsecurity1.html?gwt.codesvr=127.0.0.1:9997:

    —> Problem: No authentication prompt displayed !!!!
  • However, when we click on Send button, the authentication prompt id displayed!
  • Authenticate you with the admin account (admin/mdp4admin) (If we click again on the Send button, as expected, no authentication prompt displayed):

    —> Problem: THE FIRST SCREEN IS NOT SECURIZED BECAUSE NO AUTHENTICATION PROMPT DISPLAYED !!!!



3. Deployment on Tomcat server

  • If we deploy this application on Tomcat server. To deploy an application on the Tomcat server see the post GWT/GAE: Deployment an application on external server TOMCAT.
  • Open the URL http://localhost:8080/huojavagwtgaespringsecurity1/Huojavagwtgaespringsecurity1.html:

    —> OK: The authentication prompt is displayed !!!!
  • Authenticate you with the admin account (admin/mdp4admin), the first screen is securized!

    —> OK: THE FIRST SCREEN IS SECURIZED BECAUSE THE AUTHENTICATION PROMPT IS DISPLAYED !!!!



4. Deployment on Google Cloud

  • Go to the Google’s Cloud (GAE) dashboard at the URL http://appengine.google.com/ and create an application with the application identification (ID) equals to huojavagwtgaespringsecurity1.
    It is necessary to configure this information in the App Engine Settings… of our Eclispe project:

    Note: These informations (application ID…etc) concerning the App Engine Config in a Eclipse Project are stored in the appengine-web.xml file of the project.

    <?xml version="1.0" encoding="utf-8"?>
    <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
      <application>huojavagwtgaespringsecurity1</application>
      <version>1</version>
    ...
    </appengine-web-app>
    
  • After deployment of our huojavagwtgaespringsecurity1 application on GAE, it will be available on App Engine and accessible via http://huojavagwtgaespringsecurity1.appspot.com/Huojavagwtgaespringsecurity1.html:

    —> Problem: No authentication prompt displayed !!!!
  • However, when we click on Send button, the authentication prompt id displayed!
  • Authenticate you with the admin account (admin/mdp4admin) (If we click again on the Send button, as expected, no authentication prompt displayed):

    —> Problem: THE FIRST SCREEN IS NOT SECURIZED BECAUSE NO AUTHENTICATION PROMPT DISPLAYED !!!!



5. Origins of problem and Solution
Problem: So, we have the fact that the first screen/page Huojavagwtgaespringsecurity1.html is not securized by Spring Security only on Jetty server and Google Cloud., however, on Tomcat server, no problem.
After more investigations, the origins of problem are described in the documentation:

"Note: Static files, files that are served verbatim to users such as images, CSS or JavaScript, are handled separately from paths mentioned in the deployment descriptor. A request for a URL path that matches a path to a file in the WAR that's considered a static file will serve the file, regardless of servlet and filter mappings in the deployment descriptor. You can exclude files from those treated as static files using the appengine-web.xml file."

…so, on the cloud, the static resources are treated separately, and the Spring Security based on a Http/Servlet filter can not work. Thus, HTML and Javascript resources are considered static resources, and they are not supported by the Spring Security filter. Only calls asynchronous (AJAX) to the server fails (because the user is not authenticated), but it is already too late because JS is already downloaded on the client.

Solution:The solution is very simple: rename your HTML pages to JSP! So, they are filtered and JS resources are loaded after authentication.



6. Try the solution & Tests
Create a copy of our HTML page Huojavagwtgaespringsecurity1.html in JSP format named Huojavagwtgaespringsecurity1.jsp in the Eclispe project:

In order to check the accesses of 3 defined roles (ROLE_ADMIN, ROLE_USER and ROLE_NONE), we create a folder admin in the folder huojavagwtgaespringsecurity1\war\ containing a simple JSP page named admin.jsp:

<!doctype html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>Admin Interface</title>
  </head>
  <body>
    <h1>Admin Console</h1>
  </body>
</html>

Tests done on three servers:
JETTY:

  • http://localhost:8888/Huojavagwtgaespringsecurity1.html:
    –> NOK No authentication prompt displayed: this problem is known and linked to static resources in GAE
    –> Click sur “Send”: The authentication prompt is displayed because a request has been sent to no static resource on server.
  • http://localhost:8888/Huojavagwtgaespringsecurity1.jsp:
    –> With the account “tudu/mdp4tudu”: OK the authentication prompt displayed!!
    –> With the account “admin/mdp4admin”: OK the authentication prompt displayed!!
    –> With the account “guest/mdp4guest”: OK the authentication prompt displayed, but, we obtain a “HTTP 403 – Access is denied” response owing to the role restriction.
  • http://localhost:8888/admin/admin.jsp:
    –> With the account “tudu/mdp4tudu”: OK the authentication prompt displayed, but, we obtain a “HTTP 403 – Access is denied” response owing to the role restriction.
    –> With the account “admin/mdp4admin”: OK the authentication prompt displayed!!
    –> With the account “guest/mdp4guest”: OK the authentication prompt displayed, but, we obtain a “HTTP 403 – Access is denied” response owing to the role restriction.

TOMCAT:

  • http://localhost:8080/huojavagwtgaespringsecurity1/Huojavagwtgaespringsecurity1.html:
    –> With the account “tudu/mdp4tudu”: OK the authentication prompt displayed!!
    –> With the account “admin/mdp4admin”: OK the authentication prompt displayed!!
    –> With the account “guest/mdp4guest”: OK the authentication prompt displayed, but, we obtain a “HTTP 403 – Access is denied” response owing to the role restriction.
    server.
  • http://localhost:8080/huojavagwtgaespringsecurity1/Huojavagwtgaespringsecurity1.jsp:
    –> With the account “tudu/mdp4tudu”: OK the authentication prompt displayed!!
    –> With the account “admin/mdp4admin”: OK the authentication prompt displayed!!
    –> With the account “guest/mdp4guest”: OK the authentication prompt displayed, but, we obtain a “HTTP 403 – Access is denied” response owing to the role restriction.
  • http://localhost:8080/huojavagwtgaespringsecurity1/admin/admin.jsp:
    –> With the account “tudu/mdp4tudu”: OK the authentication prompt displayed, but, we obtain a “HTTP 403 – Access is denied” response owing to the role restriction.
    –> With the account “admin/mdp4admin”: OK the authentication prompt displayed!!
    –> With the account “guest/mdp4guest”: OK the authentication prompt displayed, but, we obtain a “HTTP 403 – Access is denied” response owing to the role restriction.

GAE:

  • http://huojavagwtgaespringsecurity1.appspot.com/Huojavagwtgaespringsecurity1.html:
    –> NOK No authentication prompt displayed: this problem is known and linked to static resources in GAE
    –> Click sur “Send”: The authentication prompt is displayed because a request has been sent to no static resource on server.
  • http://huojavagwtgaespringsecurity1.appspot.com/Huojavagwtgaespringsecurity1.jsp:
    –> With the account “tudu/mdp4tudu”: OK the authentication prompt displayed!!
    –> With the account “admin/mdp4admin”: OK the authentication prompt displayed!!
    –> With the account “guest/mdp4guest”: OK the authentication prompt displayed, but, we obtain a “HTTP 403 – Access is denied” response owing to the role restriction.
  • http://huojavagwtgaespringsecurity1.appspot.com/admin/admin.jsp:
    –> With the account “tudu/mdp4tudu”: OK the authentication prompt displayed, but, we obtain a “HTTP 403 – Access is denied” response owing to the role restriction.
    –> With the account “admin/mdp4admin”: OK the authentication prompt displayed!!
    –> With the account “guest/mdp4guest”: OK the authentication prompt displayed, but, we obtain a “HTTP 403 – Access is denied” response owing to the role restriction.

Source: huojavagwtgaespringsecurity1

Notes: This file huojavagwtgaespringsecurity1.zip contains the project of this article but it needs to add the libraries (for GWT and GAE) appengine-api-1.0-sdk-1.6.1.jar, appengine-api-labs-1.6.1.jar, appengine-jsr107cache-1.6.1.jar, datanucleus-appengine-1.0.10.final.jar, datanucleus-core-1.1.5.jar, datanucleus-jpa-1.1.5.jar, geronimo-jpa_3.0_spec-1.1.1.jar, geronimo-jta_1.1_spec-1.1.1.jar, google_sql.jar, gwt-servlet.jar, jdo2-api-2.3-eb.jar, jsr107cache-1.1.jar, (for spring security: I know all librairies are not mandatory) aopalliance-1.0.jar, asm.jar, aspectjrt-1.6.8.jar, aspectjweaver-1.6.8.jar, cglib-2.2.2.jar, commons-logging-1.1.1.jar, javassist-3.4.ga.jar, jstl-1.2.jar, spring-security-config-3.0.5.RELEASE.jar, spring-security-core-3.0.5.RELEASE.jar, spring-security-web-3.0.5.RELEASE.jar, spring-aop-3.0.3.RELEASE.jar, spring-asm-3.0.5.RELEASE.jar, spring-beans-3.0.5.RELEASE.jar, spring-context-support-3.0.5.RELEASE.jar, spring-context-3.0.5.RELEASE.jar, spring-core-3.0.5.RELEASE.jar, spring-expression-3.0.5.RELEASE.jar, spring-tx-3.0.3.RELEASE.jar, spring-web-3.0.5.RELEASE.jar and spring-webmvc-3.0.5.RELEASE.jar.

That’s all!!!

Best regards,

Huseyin OZVEREN