Skip navigation
2013

Why Restful?

 

  • Restful is popular alternative to SOAP web service and It is easy to use.

    

How do you secure your restful web service?

 

  • Because each restful request is a stateless request, so you can’t use standard login page to authenticate a user anymore.
  • The solution is to use Http Authentication header, spring security framework.
  • I am going to show you how to create your own interceptor to authenticate user requests and use secured annotation to protect your method

    

Sequence Diagram

 

  • This diagram show Spring Security can protect your Java server side resource.
  • The Client makes a request to the server side service.
  • YourOwnSecurityInterceptor intercepts the request and extract the Authentication header.
  • YourOwnSecurityInterceptor calls AuthercationManger to authticate the user.

 

 

 

springsecurity.jpg

YourOwnSecurityInterceptor.java

 

 

public class AuthenticationInterceptor extends HandlerInterceptorAdapter {

       

   private AuthenticationManager authenticationManager;

   private static final Logger logger = LoggerFactory.getLogger(AuthenticationInterceptor.class);

 

    public boolean preHandle(HttpServletRequest request,

            HttpServletResponse response, Object handler) throws Exception {

          

          String authorization = request.getHeader("Authorization");

 

          if (authorization == null) {

             

              return false;

          }

 

          String[] credentials = decodeHeader(authorization);

          assert credentials.length == 2;

          Authentication authentication = new UsernamePasswordAuthenticationToken(credentials[0], credentials[1]);

         

          Authentication successfulAuthentication = authenticationManager.authenticate(authentication);

          SecurityContextHolder.getContext().setAuthentication(successfulAuthentication);

        return true;

    }

 

 

    public String[] decodeHeader(String authorization) {

    

        try {

            byte[] decoded = Base64.decode(authorization.substring(6).getBytes("UTF-8"));

            String credentials = new String(decoded);

            return credentials.split(":");

        } catch (UnsupportedEncodingException e) {

            throw new UnsupportedOperationException(e);

        }

    }

 

 

       

   

}

 

 

 

 

Spring Configuration

 

  1. Web.xml:

 

    <context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>

    </context-param>

 

    <listener>

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

    </listener>

   

    <listener>

                <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>

        </listener>

 

 

    <servlet>

        <servlet-name>mvc-dispatcher</servlet-name>

        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

      

        <load-on-startup>1</load-on-startup>

    </servlet>

   

    <servlet-mapping>

        <servlet-name>mvc-dispatcher</servlet-name>

        <url-pattern>/rest/*</url-pattern>

    </servlet-mapping>

 

 

 

Mvc-dispatcher-servlet.xml

 

<context:component-scan base-package="com.johnnyweb.stockWatcher.controller" />

    <mvc:annotation-driven />

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

secured-annotations="enabled"

 

    <mvc:interceptors>

        <bean id="authenticationInterceptor" class="com.johnnyweb.interceptor.AuthenticationInterceptor">

                        <property name="authenticationManager" ref="authenticationManager" />

                </bean>

        </mvc:interceptors>

 

    <security:authentication-manager  alias="authenticationManager">

                <security:authentication-provider>

                        <security:user-service id="userService">

                         <security:user name="gwtrest" password="gwtrest" authorities="ROLE_CUSTOMER" />

                             <security:user name="gwtAdmin" password="gwtAdmin" authorities="ROLE_ADMIN" />

                        </security:user-service>

                </security:authentication-provider>

        </security:authentication-manager>

 

Spring controller

 

 

@RequestMapping(method = RequestMethod.GET)

 

@Secured("ROLE_ADMIN")

 

        public @ResponseBody List<StockPrice> getStocks( @RequestParam(value = "q", required = false) final String q ) {

                       

                String[] stockSymbols = q.split(" ");

                ArrayList<StockPrice> stockPriceList= new ArrayList<StockPrice>();

                    for (String stockSymbol : stockSymbols) {

                     Random rnd = new Random();

                      double price = rnd.nextDouble() * MAX_PRICE;

                      double change = price * MAX_PRICE_CHANGE * (rnd.nextDouble() * 2f - 1f);

                      StockPrice stockPrice = new StockPrice();

                          stockPrice.setSymbol(stockSymbol);           

                          stockPrice.setPrice(price);

                          stockPrice.setChange(change);

                          stockPriceList.add(stockPrice);                 

                    }

               

               

                return stockPriceList;

}

 

       

 

Test your restful service using FIrefox RestClient

 

 

http://localhost:8080/SpringMVC/rest/stockWatcher?q=NN

 

Why Restful?

 

  • Restful is popular alternative to SOAP web service and It is easy to use.

    

How do you secure your restful web service?

 

  • How do you protect server side resources to allow only certain authenticated users to access? Because each restful request is a stateless request, so you can’t use standard login page to authenticate a user anymore.
  • The solution is to use Http Authentication header and spring security framework.
  • There are many ways to use Spring Security to authenticate user request. In this paper I am going to show you how to use FilterSecurityInterceptor to authenticate user requests

    

Sequence Diagram

 

seq.png

 

  • This diagram show Spring Security can protect your Java server side resource.
  • The Client makes a request to the server side service.
  • Spring FilterSecurityInterceptor intercepts the request and extract the Authentication header.
  • Spring FilterSecurityInterceptor calls AuthercationManger to authticate the user.
  • Spring FilterSecurityInterceptor use AccessManager to decide if the system is going to allow the user to access the protected resource. 

 

Spring Configuration

 

  1. Web.xml:

 

    <context-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>

    </context-param>

 

    <listener>

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

    </listener>

   

    <listener>

                <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>

        </listener>

 

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

 

    <servlet>

        <servlet-name>mvc-dispatcher</servlet-name>

        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

      

        <load-on-startup>1</load-on-startup>

    </servlet>

   

    <servlet-mapping>

        <servlet-name>mvc-dispatcher</servlet-name>

        <url-pattern>/rest/*</url-pattern>

    </servlet-mapping>

 

 

 

 

Mvc-dispatcher-servlet.xml

<context:component-scan base-package="com.johnnyweb.stockWatcher.controller" />

    <mvc:annotation-driven />

 

    <security:authentication-manager>

                <security:authentication-provider>

                        <security:user-service id="userService">

                                <security:user name="gwtrest" password="gwtrest" authorities="customer" />

                        </security:user-service>

                </security:authentication-provider>

        </security:authentication-manager>

 

        <security:http create-session="stateless" use-expressions="true">

               

                <security:intercept-url pattern="/**"

                        access="hasAnyRole('customer')" />

                <security:http-basic />

        </security:http>

 

 

Spring controller

 

 

@RequestMapping(method = RequestMethod.GET)

        public @ResponseBody List<StockPrice> getStocks( @RequestParam(value = "q", required = false) final String q ) {

                       

                String[] stockSymbols = q.split(" ");

                ArrayList<StockPrice> stockPriceList= new ArrayList<StockPrice>();

                    for (String stockSymbol : stockSymbols) {

                     Random rnd = new Random();

                      double price = rnd.nextDouble() * MAX_PRICE;

                      double change = price * MAX_PRICE_CHANGE * (rnd.nextDouble() * 2f - 1f);

                      StockPrice stockPrice = new StockPrice();

                          stockPrice.setSymbol(stockSymbol);           

                          stockPrice.setPrice(price);

                          stockPrice.setChange(change);

                          stockPriceList.add(stockPrice);                 

                    }

               

               

                return stockPriceList;

}

 

       

 

Test your restful service using FIrefox RestClient

 

 

http://localhost:8080/SpringMVC/rest/stockWatcher?q=NN