Tag Archives: Maven

Securing Restful web services using Spring-Security

After several months of silent, I woke up… With some security interests!
The security is a common requirement on many web projects, and fortunately, Spring helps us to implement it.
The most common way to do it is just defining a set of rules and letting Spring manage the login and so on.
In this demo, I will use Spring-boot (for its simplicity) but the security configuration is exactly the same with a web application.
And to be clear, I do not have the pretentiousness that this is THE way to follow when you need to secure your web services and I am convinced that someone else found another way to do it, but this is my solution, I used it several times, and it works perfectly, so maybe it will help someone else… One day 🙂

To start simply, I just built a simple web site with 2 pages:

  • the home page (/index.html), which is freely accessible
  • and another page (/secured/page.html) which is in a restricted area

Using Spring-boot, the structure is something like:

structure

By default, Spring boot published everything under the static directory and is accessible via http://localhost:8080/

For instance, everybody can access to our pages, it’s time to remedy to that state.

Let’s start with the interesting part of the Maven Configuration:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.3.2.RELEASE</version>
	<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<java.version>1.8</java.version>
</properties>

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-security</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

The starter dependencies are somehow facilitators provided by Spring boot to add some dependencies, I think that we can guess their purpose just by their name. For more information about this pom, you can have a look to the Spring-boot site.

Now, we have to restrict access to the secured part of the site, this is done here:

@Configuration
@EnableWebSecurity
public class SecurityJavaConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().
          withUser("admin").password("password").roles("ADMIN", "USER").and().
          withUser("user").password("password").roles("USER");
    }
 
    @Override
    protected void configure(HttpSecurity http) throws Exception { 
        http
        .authorizeRequests()
        .antMatchers(HttpMethod.GET, "/secured/**").access("hasRole('USER')");
        
        //indicate that we are user login form authentication
        http.formLogin();
    }
}

For the demo, I define my users directly in the application, this is AuthenticationManagerBuilder.inMemoryAuthentication().

Inside the configure(HttpSecurity http) method, you can see that I just defined the URL of the secured part, indicating who can access it based on role.
And finally, I indicate that I want to use the form login authentication as it is provided by Spring.

According to the configuration, the users can access freely the home page, but only the users authenticated and with the right role can access to the secured part. This is a perfect configuration for a standard web site, but remember that we nee to secure a web service, the redirection to a login form is not an acceptable way for that purpose and we need to customise this behavior.

The first issue to solve is to avoid to redirection to the login form in case of unauthenticated access, I do it by changing the AuthenticationEntryPoint with mine:

@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
	@Override
	public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
			throws IOException, ServletException {
		response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
	}
}

As you can see, this is very simple, I just need to send the right HTTP code to inform my client that it needs to authenticate before accessing the resource it requested.
And to indicate to Spring that I slightly changed the authentication, it is very complicated because… Well, it’s Spring, so, I just need to add the following in my SecurityJavaConfig:

[...]
@Autowired
private AuthenticationEntryPoint authenticationEntryPoint;
[...]
protected void configure(HttpSecurity http) throws Exception {
	http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
}

Now, when someone… As we are dealing with web services,I should say something tries to access to secured resources, it just receives an unauthorized HTTP code instead of a redirection to the login page.
That’s a good point but we have also to manage the successful and erroneous authentication. Instead of redirecting to a page, we have to inform the client that the credentials are valid or not .
For each case, we need to define two different classes:

  • in case of success, we let Spring clean-up the temporary data:
    @Component
    public class RestAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    	@Override
    	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
    			Authentication authentication) throws IOException, ServletException {
    		clearAuthenticationAttributes(request);
    	}
    }
    
  • in case of error, we return an HTTP code and an optional message:
    @Component
    public class RestAuthenticationFailureHandler implements AuthenticationFailureHandler{
    	@Override
    	public void onAuthenticationFailure(HttpServletRequest arg0, HttpServletResponse arg1, AuthenticationException arg2)
    			throws IOException, ServletException {
    		arg1.sendError(HttpServletResponse.SC_FORBIDDEN, "Wrong username or password");
    	}
    }
    
  • And then the last step is to add them to the Spring configuration:

    [...]
    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;
    
    @Autowired
    private AuthenticationSuccessHandler authenticationSuccessHandler;
    [...]
    protected void configure(HttpSecurity http) throws Exception {
    	[...]
    	FormLoginConfigurer formLogin = http.formLogin();
    	[...]
    	formLogin.successHandler(authenticationSuccessHandler);
    	formLogin.failureHandler(authenticationFailureHandler);
    
    }
    

    Now, we can define our web services, and Spring will manage authentication for us.
    To protect your services, obviously, you need to add something like:

    http
    .authorizeRequests()
    [...]
    .antMatchers(HttpMethod.GET, "/secured/services/**")
    .access("hasRole('SERVICE_USER')");
    

    And you can also restrict access by the HTTP methods, someone can read data (GET method) but could not be allowed to modify it (POST/PUT methods).
    That’s it!

    In a next post, I will show how I used it with Angular-js, stay tuned 😀

    (the full project is available on Github)

Oracle proxy user with Spring

The standard solution to manage the database connections in a web application is to let the server manage it, and use Spring to inject it wherever it is needed. By doing so, we can let also the transaction management to be done by a third party API, Spring fits perfectly this need.
But this option assumes that the user/password used to connect to the database are the server responsibility. But sometimes…
I had a project of migration of a heavy client written in Visual Basic into a web application, and this application uses a connection per user, meaning that the credentials are user specific.
This should not be an issue except if the Visual Basic application makes an heavy usage of Oracle variables, and, unfortunately, it was the case. It means that, for each HTTP request, we need to connect to the database by creating a new connection with the connected user credentials. This kind of behavior is resource consuming and this is something that we commonly address with a pool of connections.

To remedy to that situation, luckily, Oracle provides a mechanism to reflect this usage. The idea is to define a user proxy which will be used by the real user to connect through:

>CREATE USER proxy_user IDENTIFIED BY password;

>ALTER USER scott GRANT CONNECT THROUGH proxy_user;

Now, we can create a datasource with this proxy user and use the real user to access to the data.

But now, what about our application?
Fortunately, Spring provides classes to manage this particular database configuration but it does not allow us to use the server managed datasource.
The Maven dependency we need to add:

<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-oracle</artifactId>
	<version>1.0.0.RELEASE</version>
</dependency> 

And the Spring configuration:

<?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:orcl="http://www.springframework.org/schema/data/orcl"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/data/orcl http://www.springframework.org/schema/data/orcl/spring-data-orcl-1.0.xsd">

<orcl:pooling-datasource id="dataSource"
	url="jdbc:oracle:thin:@${net.classnotfound.jdbc.server}:${net.classnotfound.jdbc.port}:${net.classnotfound.jdbc.sid}"
	username="${net.classnotfound.jdbc.user}" 
	password="${net.classnotfound.jdbc.password}">
	<orcl:connection-properties>validationQuery=select 1 from dual</orcl:connection-properties>
	<orcl:connection-cache-properties>
		ValidateConnection=true
	</orcl:connection-cache-properties>
	<orcl:username-connection-proxy connection-context-provider="usernameProvider" />
</orcl:pooling-datasource>

<bean id="usernameProvider" class="net.classnotfound.core.jdbc.support.UserProvider" />

<bean id="transactionManager"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
	depends-on="dataSource">
	<property name="dataSource" ref="dataSource" />
</bean>

We see that we have to use a specific namespace to define the datasource and the attribute are enough explicit.

The user-name-connection-proxy is used to provide the username of the connected user. In my case, as I am using Spring-Security for that purpose, the user provider looks like:

package net.classnotfound.core.jdbc.support;

import org.springframework.data.jdbc.support.ConnectionUsernameProvider;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

public class UserProvider implements ConnectionUsernameProvider {
    /**
     * return the username of the current security context
     * 
     * @return the user provided by the current request
     */
    @Override
    public String getUserName() {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (principal instanceof UserDetails) {
            return ((UserDetails) principal).getUsername();
        } else {
            return principal.toString();
        }
    }
}

Basically, it gets the information from the Spring Security context and returns the username.

Define Restful web services using Spring

In one of my project, I had the difficult decision to switch to another technology: I replaced JSF with Angular-JS.
Our goal was to speed up the development by removing the painful part implied with JSF, as a lot of server requests to manage, some view state issues, the refresh management, the need to implement the view on the Java part with its managed beans, etc…

But the big impact on the architectural point of view was that we have to move the GUI (and its logic) on the client side and give access to the data. Fortunately, this part was ease by the layered structure of the application, I just need to replace the old JSF part with a REST interface which is accessed by the Angular-JS components using Ajax requests.
As the project used already Spring, I decided to use it also to set up the restful part, I describe hereafter what I did.

First of all, we need to add the corresponding dependencies in our POM:

<properties>
    <spring.framework.version>4.0.5.RELEASE</spring.framework.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.framework.version}</version>
    </dependency>
            <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.framework.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.3.4</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.9.12</version>
    </dependency>
</dependencies>

We need also to activate the configuration using annotation, for that we have to add in our Spring configuration file:

    <context:component-scan base-package="net.classnotfound.ws"/>
    <mvc:annotation-driven />

Even if I do not like to use the annotations to configure the application, I decided to make an exception for the web services, as they are not intended to have some intelligence and are just a bridge to the business layer, I consider it as acceptable.

A web service is declared using the @RestController Spring annotation:

package net.classnotfound.ws.controller;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {
	//Web service implementation here
    
}

When we define an endpoint for the web service, we need to indicates which HTTP method we use, the type of data we expect (JSON is the usual case), etc…
This can be done easily by using the Spring annotation:

    @RequestMapping(value = "/service/print", method = RequestMethod.POST, consumes = {"application/json" })
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void print(@RequestBody final Data data) {
        System.out.println(data);
    }

Here, we defined a method print, which is reachable using “/service/print” URL, using a POST request with data in JSON format.
The @ResponseStatus is used to define the HTTP return code to be used.

Another option is to use a GET method, but doing this, the parameters are now directly provided with the requested URL:

    @Autowired
    private DataService dataService;

    @Transactional
    @Globals
    @RequestMapping(value = "/service/data/{id}", method = RequestMethod.GET)
    @ResponseBody
    public Data find(@PathVariable("id") final String id) {
        Data data = dataService.find(id);
        if (data==null) {
            throw new ObjectNotFoundException(id);
        }
        return data;
    }

We can see the parameter defined in the URL using a EL syntax and this parameter is also mentioned in the signature of the method using @PathVariable annotation.

Too easy, isn’t it? 😀

Display Maven release number in JSF page

In the web projects, it is often useful to see quickly the version of the deployed application. A simple solution is to get it from Maven and display it in our page, in footer or a “about” page.
The main idea is to use a property file as a JSF resource as we can use, for example, when we have a i18n requirement.
For that, I put a property file version.properties with content in the resource directory:

version=${version}
revision=${buildNumber}

The version is the version defined in our project pom and it is automatically provided by Maven.
The revision is the revision number of the last build provided by SVN, to get it, I will need another Maven plugins.

Now, I need to tell to JSF to use this file as resource file, I do it in my faces-config.xml:

<application>
	<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
	<resource-bundle>
	   <base-name>version</base-name>
	   <var>vers</var>
	</resource-bundle>
</application>

And to display it in our JSF pages, I add:

<body>
   [...]
	<div>classNotFound.net ©2014 -
		v#{vers.version} - #{vers.revision}</div>
</body>

If I try to access to this page, I will not see the version/revision, to do that, I have to ask Maven to filter the properties files and replace the variables.
In my pom.xml, I add:

<build>
	<resources>
		<resource>
			<directory>src/main/resources</directory>
			<filtering>true</filtering>
			<includes>
				<include>**/*</include>
			</includes>
		</resource>
	</resources>
</build>

To have the build number, I have to use 3 Maven plugins:

<pluginManagement>
        <plugins>
            <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>buildnumber-maven-plugin</artifactId>
            <executions>
                <execution>
                    <phase>validate</phase>
                    <goals>
                        <goal>create</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <doCheck>false</doCheck>
                <doUpdate>false</doUpdate>
                <providerImplementations>
                    <svn>javasvn</svn>
                </providerImplementations>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>com.google.code.maven-scm-provider-svnjava</groupId>
                    <artifactId>maven-scm-provider-svnjava</artifactId>
                    <version>2.0.2</version>
                </dependency>
                <dependency>
                    <groupId>org.tmatesoft.svnkit</groupId>
                    <artifactId>svnkit</artifactId>
                    <version>1.7.5-v1</version>
                </dependency>
            </dependencies>
        </plugin>
        </plugins>
    </pluginManagement>
  </build>
  
    <scm>
        <connection>scm:svn:https://forge.classnotfound.net/svn/version/trunk/project/project-web</connection>
        <developerConnection>scm:svn:https://forge.classnotfound.net/svn/project/trunk/project/project-web</developerConnection>
        <url>https://forge.classnotfound.net/svn/project/trunk/project/project-web</url>
    </scm>

Now, it works.

Change web context using Maven

<packaging>war</packaging>
<build>
<plugins>
  <plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.1.1</version>
    <configuration>
        <packagingExcludes>WEB-INF/web.xml</packagingExcludes>
        <warName>exp-elec-web</warName>
    </configuration>
</plugin>
</plugins>
</build>

Maven config for JSF2/RichFaces

Here is my Maven configuration for a JSF2/Richfaces project:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>net.classnotfound</groupId>
    <artifactId>jsf</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>jsf</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <org.apache.myfaces.version>2.2.0</org.apache.myfaces.version>
        <org.richfaces.version>4.3.5.Final</org.richfaces.version>
    </properties>

    <dependencies>

        <!-- web container dependencies -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper</artifactId>
            <version>7.0.50</version>
            <scope>provided</scope>
        </dependency>
        <!-- JSF dependencies -->
        <dependency>
            <groupId>org.apache.myfaces.core</groupId>
            <artifactId>myfaces-bundle</artifactId>
            <version>${org.apache.myfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-digester</groupId>
            <artifactId>commons-digester</artifactId>
            <version>2.1</version>
        </dependency>
        <!-- end JSF dependencies -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!-- RichFaces dependencies -->
        <dependency>
            <groupId>org.richfaces.core</groupId>
            <artifactId>richfaces-core-api</artifactId>
            <version>${org.richfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.richfaces.core</groupId>
            <artifactId>richfaces-core-impl</artifactId>
            <version>${org.richfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.richfaces.ui.common</groupId>
            <artifactId>richfaces-ui-common-api</artifactId>
            <version>${org.richfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.richfaces.ui.core</groupId>
            <artifactId>richfaces-ui-core-api</artifactId>
            <version>${org.richfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.richfaces.ui</groupId>
            <artifactId>richfaces-components-api</artifactId>
            <version>${org.richfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.richfaces.ui</groupId>
            <artifactId>richfaces-components-ui</artifactId>
            <version>${org.richfaces.version}</version>
        </dependency>
        <dependency>
            <groupId>org.w3c.css</groupId>
            <artifactId>sac</artifactId>
            <version>1.3</version>
        </dependency>
        <!-- End RichFaces dependencies -->
    </dependencies>
</project>

Define the Java version in Maven

Directly in the pom.xml (resource definition is also included):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
...
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
        <resources>
            <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
                <include>**/*</include>
            </includes>
            <excludes>
                <exclude>profiles/**</exclude>
            </excludes>
            </resource>
            <resource>
                <directory>src/main/resources/profiles/${profile.name}</directory>
                <includes>
                    <include>*.properties</include>
                    <include>*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>