title: RESTful Web Service with Jersey and Apache Shiro
body: <p>My first attempt at developing a simple authentication based REST services. I am trying to develop a RESTful web application using Jersey on Tomcat 8. I am using Apache Shiro for session management and authorization. Only HTTPS is supported.<br>
  All services require authentication, neither guest nor anonymous access is allowed. The request can be authenticated two ways.  </p>
  
  <ol>
  <li>If the user belongs to the list of users in web application, then the user logs in from a Web browser and Shiro simply validates if the current user is logged in and allows request to proceed. This is for the custom UI provided by the application itself.  </li>
  <li>If the request is from third party application, the username/password token are passed into the HTTP header authorization field for every service request. The users are managed by third party app and the app uses a common username/password for its users to access the web service. Such common users are prevented from logging in.</li>
  </ol>
  
  <p>All service requests are filtered (web.xml):  </p>
  
  <pre><code>&lt;servlet&gt;
      &lt;servlet-name&gt;REST Service&lt;/servlet-name&gt;
      &lt;servlet-class&gt;com.sun.jersey.spi.container.servlet.ServletContainer&lt;/servlet-class&gt;
      &lt;init-param&gt;
          &lt;param-name&gt;com.sun.jersey.spi.container.ContainerRequestFilters&lt;/param-name&gt;
          &lt;param-value&gt;com.unisys.cpf.ffm.filter.AuthenticationFilter&lt;/param-value&gt;
      &lt;/init-param&gt;
  &lt;/servlet&gt;
  &lt;servlet-mapping&gt;`enter code here`
      &lt;servlet-name&gt;REST Service&lt;/servlet-name&gt;
      &lt;url-pattern&gt;/service/*&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;  
  </code></pre>
  
  <p>The <code>AuthenticationFilter</code> class implements <code>ContainerRequestFilter</code> for authentication:  </p>
  
  <pre><code>@Override
  public ContainerRequest filter(ContainerRequest cr) {
      Subject currentUser = SecurityUtils.getSubject();
      if (!currentUser.isAuthenticated()) {
          //User is not logged in so get the authorization from header and authenticate
          String auth = cr.getHeaderValue("authorization");
          //Do Shiro authentication here.
      }
      return cr;
  }
  </code></pre>
  
  <p>I have a web service which accepts form parameters and creates a resource. The Form parameters are dynamic based on what user selects. So I cannot use @FormParam to get all the parameters. Also there may be more contents to form as new features are added so I do not want to touch the Service again for each new/removed parameter.</p>
  
  <p>I am using the Chrome Advanced REST Client plugin to simulate third party requests. Any browser is fine for the first scenario (logged in user).
  Now I know just two ways of accessing the form parameters.  </p>
  
  <p>First method is to use <code>MultivaluedMap</code>.  </p>
  
  <pre><code>@POST
  @Path("/create")
  public String createResource(MultivaluedMap&lt;String, String&gt; parameters) {
      System.out.println("Name of the resource: " + parameters.getFirst("resourceName"));
  }
  </code></pre>
  
  <p>But trying to get the parameters using <code>MultivaluedMap</code> works only when a logged in  user submits the form. If I submit from REST Client plugin the same form values, then all parameters return null.</p>
  
  <p>Second method is to use <code>@Context HttpServletRequest</code> </p>
  
  <pre><code>@POST
  @Path("/create")
  public String createResource(@Context HttpServletRequest request) {
      System.out.println("Name of the resource: " + request.getParameter("resourceName"));
  }
  </code></pre>
  
  <p>This works for REST Client but does not work if a logged in user submits form. All request.getParameter return null.</p>
  
  <p>If anybody knows how to fix the problem or better way to do authentication, then please let me know.</p>