Saturday, February 16, 2013

Spring Security and Http Basic Authentication

This article will show you how to use Spring Security to protect your web application with Http Basic Authentication.



Our application will require that users will authenticate themeselves with Http Basic Authentication. Unauthorized users will get 401 UNAUTHORIZED response and will have to authenticate themselves with login and password.

I expect that your application is already using Spring Framework and Maven. So, to start using Spring Security we need to add these maven dependencies:

<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-config</artifactId>
   <version>3.1.3.RELEASE</version>
</dependency>
<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-web</artifactId>
   <version>3.1.3.RELEASE</version>
</dependency>

We need to add Spring Security Filter to web.xml configuration so that it will intercept all HTTP requests.

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


Then we need to implement a UserService that checks that the user exists (e.g. in a database).

public class UserServiceImpl implements UserService {

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

   @Override
   public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

      if (users.containsKey(username)) {
         return users.get(username);
      }

      throw new UsernameNotFoundException("User " + username + " not found");
   }
}


The next step is to implement a BasicAuthenticationEntryPoint that would tell users that they have to authenticate in order to access this application.

public class VozisBasicAuthenticationEntryPoint extends 
BasicAuthenticationEntryPoint {

@Override
public void commence(HttpServletRequest request, HttpServletResponse response, 
AuthenticationException authException) throws IOException, ServletException {
      response.addHeader("WWW-Authenticate", "Basic realm=\"" + 
         getRealmName() + "\"");
      response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
      PrintWriter writer = response.getWriter();
      writer.println("HTTP Status " + HttpServletResponse.SC_UNAUTHORIZED + 
         " - " + authException.getMessage());
   }
}

Now we have all components that we need, let's integrate them together. Below is the example of security.xml configuration:

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

   <global-method-security secured-annotations="enabled" />

   <http auto-config="false" create-session="stateless">
      <http-basic entry-point-ref="authenticationEntryPoint" />
   </http>

   <beans:bean id="authenticationEntryPoint"
     class="com.blogspot.vozis.security.VozisBasicAuthenticationEntryPoint">
      <beans:property name="realmName" value="Vozis" />
   </beans:bean>

   <authentication-manager alias="authenticationManager">
      <authentication-provider user-service-ref="userService" />
   </authentication-manager>

   <beans:bean id="userService" class="com.blogspot.vozis.security.UserServiceImpl" />
</beans:beans>   




2 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Thank you for this super helpful post. We still need to configure web.xml to register security.xml file. Is that correct?

    Something like: http://pastebin.com/JMpEpiur

    ReplyDelete