Enterprise Integration Zone is brought to you in partnership with:

Faheem is a software programmer and architect working primarily with the Java stack for the last 8 years. Loves to write about technology. He's interested in messaging systems, distributed systems, cloud computing, NoSQL and web frameworks. Faheem is a DZone MVB and is not an employee of DZone and has posted 16 posts at DZone. You can read more from them at their website. View Full User Profile

Adding Http Basic Auth to RESTful Services in Java and Spring

06.21.2013
| 7877 views |
  • submit to reddit

Adding basic http authentication to a set of  Spring MVC based services is very simple. This tutorial teaches how to quickly setup authentication by keeping a set of usernames, passwords and roles in a spring configuration file and associating URL patterns with these for the framework to determine if a user is authorized or not. For more robust authentication and authorization where you might be using a Directory server and LDAP, additional configurations are required which are not being discussed in this post.

In this tutorial, I will work with the assumption that you already have a running application built with Spring MVC. If you do, there really are only two steps involved. Let’s start:

1. Adding Dependencies

The first thing you need to do is get the relevant spring security modules. Add these dependencies to your pom.xml

<dependency>
       <groupId>org.springframework.security</groupId>
       <artifactId>spring-security-web</artifactId>
       <version>${org.springframework.version}</version>
       <type>jar</type>
       <scope>compile</scope>
</dependency>
<dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>${org.springframework.version}</version>
        <type>jar</type>
        <scope>compile</scope>
</dependency>

2. Modifying the web.xml

The first thing we do is to add a DelegatingFilterProxy filter. This is a standard servlet filter that delegates responsibility to a Spring bean. In other words, you can provide spring support for servlet filters via the DelegatingFilterProxy. In our example, we will use the DelegatingFilterProxy to delegate authentication (and eventually authorization) responsibilities to a spring bean. Add the following XML to your 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>

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

<context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>classpath:security-context.xml</param-value>
</context-param>

3. Creating the security context xml and placing it in the classpath

In line 16 of the web.xml snippet above, I refer to a file security-context.xml. This gets loaded into the spring context at application startup and consists of our security configurations. This is what this file looks like:

<?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:security="http://www.springframework.org/schema/security"
       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.0.xsd">

<security:http auto-config='true'>
     <security:intercept-url pattern="/logs/**" access="ROLE_USER, ROLE_ADMIN"/>
     <security:intercept-url pattern="/logviewer.html" access="ROLE_USER, ROLE_ADMIN"/>
     <security:intercept-url pattern="/qr/**" access="ROLE_USER, ROLE_ADMIN"/>
     <!-- security:intercept-url pattern="/sms/**" access="ROLE_USER, ROLE_ADMIN"/-->
     <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
     <security:http-basic />
</security:http>

<security:authentication-manager>
     <security:authentication-provider>
         <security:user-service>
              <security:user name="username1" password="password1" authorities="ROLE_USER" />
              <security:user name="username2" password="password2" authorities="ROLE_USER, ROLE_ADMIN" />
              </security:user-service>
     </security:authentication-provider>
</security:authentication-manager>
</beans>

Remember to add namespace and xsd declarations for security (lines 4 and 9). From lines 13 to 17, we provide mappings of URLs against roles. The ROLE_ settings are the roles within the application where these could be roles defined in a database or groups in active directory  etc. IS_AUTHENTICATED_ANONYMOUSLY is used to specify that you can get in anonymously. Therefore the above settings allow all requests to be served anonymously without authentication except the 3 mentioned that require authentication. The intercepts are evaluated top-down which means that if <security:intercept-url pattern=”/**” access=”IS_AUTHENTICATED_ANONYMOUSLY”/> was first in the list, all requests would go through.

4. Calling the service

Let’s see what happens when we call a URL that is configured to be authenticated. We get a pop up that asks for username and password.

In case you provide an invalid user name and/or password, you get a HTTP 415 error

 Lets look at the HTTP request header when we have a successful login

 You will notice in the image above that there is a header attribute Authorization with value Basic dXNlcm5hbWUxOnBhc3N3b3JkMQ== If we decode this using any Base64 decoder, we get username1:password1. You can see that HTTP basic authentication simply takes your username and password, concatenates them as username:password and then encodes them in Base64 and sends it over the wire.

The bottom line is that HTTP basic auth is very easy to implement and better than no security at all but is vulnerable and should be replaced with more robust mechanism like Digest Authentication which I may discuss in a future post.


Published at DZone with permission of Faheem Sohail, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)