In this RESTful services tutorial series, we will see about how to intercept a request in JAX-RS restful web service. JAX-RS specification is the Java API for RESTful web services and Jersey is its reference implementation. In the previous tutorial we saw about doing authentication in REST with plain servlet filters.
In this tutorial lets march to the next step. Lets do the HTTP basic authentication for RESTful services using ContainerRequestFilter
. It is an interface in the JAX-RS specification.
ContainerRequestFilter
this is an interface and should be implemented by the container request filters.
@Provider
so that the JAX-RS runtime will discover this filter. As always, this annotation is sufficient and there is no other configuration required in web.xml
@NameBinding
annotation can be applied to match the request for filter execution.
post-match
and if we want the execution to be done before match we should use the @PreMatching
annotation.Let us see the ContainerRequestFilter
in action using an example project. I recommend you to go through the previous tutorial RESTful Services HTTP basic Authentication since we will using the same project with the exception of the filter class.
package com.javapapers.webservices.rest.jersey; import javax.ws.rs.WebApplicationException; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.core.Response.Status; import javax.ws.rs.ext.Provider; @Provider public class JaxRsFilterAuthentication implements ContainerRequestFilter { public static final String AUTHENTICATION_HEADER = "Authorization"; @Override public void filter(ContainerRequestContext containerRequest) throws WebApplicationException { String authCredentials = containerRequest .getHeaderString(AUTHENTICATION_HEADER); // better injected AuthenticationService authenticationService = new AuthenticationService(); boolean authenticationStatus = authenticationService .authenticate(authCredentials); if (!authenticationStatus) { throw new WebApplicationException(Status.UNAUTHORIZED); } } }
Just a Hello World service.
package com.javapapers.webservices.rest.jersey; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Path("/helloworld") public class HelloWorld { @GET @Produces(MediaType.TEXT_PLAIN) public String sayPlainTextHello() { return "Hello World RESTful Jersey!"; } @GET @Produces(MediaType.TEXT_XML) public String sayXMLHello() { return "<?xml version=\"1.0\"?>" + "<hello> Hello World RESTful Jersey" + "</hello>"; } @GET @Produces(MediaType.TEXT_HTML) public String sayHtmlHello() { return "<html> " + "<title>" + "Hello World RESTful Jersey" + "</title>" + "<body><h1>" + "Hello World RESTful Jersey" + "</body></h1>" + "</html> "; } }
This is a service class that takes care or parsing out the credentials and doing the auth.
package com.javapapers.webservices.rest.jersey; import java.io.IOException; import java.util.Base64; import java.util.StringTokenizer; public class AuthenticationService { public boolean authenticate(String authCredentials) { if (null == authCredentials) return false; // header value format will be "Basic encodedstring" for Basic // authentication. Example "Basic YWRtaW46YWRtaW4=" final String encodedUserPassword = authCredentials.replaceFirst("Basic" + " ", ""); String usernameAndPassword = null; try { byte[] decodedBytes = Base64.getDecoder().decode( encodedUserPassword); usernameAndPassword = new String(decodedBytes, "UTF-8"); } catch (IOException e) { e.printStackTrace(); } final StringTokenizer tokenizer = new StringTokenizer( usernameAndPassword, ":"); final String username = tokenizer.nextToken(); final String password = tokenizer.nextToken(); // we have fixed the userid and password as admin // call some UserService/LDAP here boolean authenticationStatus = "admin".equals(username) && "admin".equals(password); return authenticationStatus; } }
Remember to map your packages as below for the Jersey Runtime.
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>RESTful Jersey Hello World</display-name> <servlet> <servlet-name>RESTful Jersey Hello World Service</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>com.javapapers.webservices.rest.jersey</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>RESTful Jersey Hello World Service</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping> </web-app>
Deploy the RESTful service and invoke the following resource:
http://localhost:8080/RESTful_Jersey_Hello_World/rest/helloworld
Download the following JAR files from Jersey download bundle and add to the project lib.
aopalliance-repackaged-2.4.0-b06.jar asm-debug-all-5.0.2.jar hk2-api-2.4.0-b06.jar hk2-locator-2.4.0-b06.jar hk2-utils-2.4.0-b06.jar javassist-3.18.1-GA.jar javax.annotation-api-1.2.jar javax.inject-2.4.0-b06.jar javax.servlet-api-3.0.1.jar javax.ws.rs-api-2.0.1.jar jaxb-api-2.2.7.jar jersey-client.jar jersey-common.jar jersey-container-servlet-core.jar jersey-container-servlet.jar jersey-guava-2.15.jar jersey-server.jar org.osgi.core-4.2.0.jar osgi-resource-locator-1.0.1.jar persistence-api-1.0.jar validation-api-1.1.0.Final.jar
Comments are closed for "Intercept JAX-RS Request with Jersey ContainerRequestFilter".
Simply Great!!!