I\'ve written a simple REST server using JAX-RS, Jersey and Grizzly. This is how I start the server:
URI baseUri = UriBuilder.fromUri(\"http://localhost/api\
@aioobe be aware that although this will kind-of work you need better error checking when you're working with the header. For example:
auth = auth.replaceFirst("[Bb]asic ", "");
This assumes that the authentication header is Basic, whereas it might not be. You should check that the authorization header starts with 'Basic' and if not throw unauthorized. Same thing for ensuring that the rest of the information is actually base64-encoded.
I managed to get it working after a couple of hours, based on this blog post.
My solution involves:
I created this ContainerRequestFilter
:
public class AuthFilter implements ContainerRequestFilter {
// Exception thrown if user is unauthorized.
private final static WebApplicationException unauthorized =
new WebApplicationException(
Response.status(Status.UNAUTHORIZED)
.header(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"realm\"")
.entity("Page requires login.").build());
@Override
public ContainerRequest filter(ContainerRequest containerRequest)
throws WebApplicationException {
// Automatically allow certain requests.
String method = containerRequest.getMethod();
String path = containerRequest.getPath(true);
if (method.equals("GET") && path.equals("application.wadl"))
return containerRequest;
// Get the authentication passed in HTTP headers parameters
String auth = containerRequest.getHeaderValue("authorization");
if (auth == null)
throw unauthorized;
auth = auth.replaceFirst("[Bb]asic ", "");
String userColonPass = Base64.base64Decode(auth);
if (!userColonPass.equals("admin:toHah1ooMeor6Oht"))
throw unauthorized;
return containerRequest;
}
}
And I then changed the startup code to include the filter:
URI baseUri = UriBuilder.fromUri("http://localhost/api")
.port(8081)
.build();
ResourceConfig rc = new PackagesResourceConfig("se.aioobe.resources");
// Add AuthFilter ////////////
rc.getProperties().put("com.sun.jersey.spi.container.ContainerRequestFilters",
"<YOUR PACKAGE FOR AuthFilter>.AuthFilter");
//////////////////////////////
HttpServer httpServer = GrizzlyServerFactory.createHttpServer(baseUri, rc);
You may want to check HTTPS Client Server Grizzly sample distributed with Jersey which exactly does that. Here is a gist from that sample on configuring security filters on the Grizzly server.
WebappContext context = new WebappContext("context");
ServletRegistration registration =
context.addServlet("ServletContainer", ServletContainer.class);
registration.setInitParameter("com.sun.jersey.config.property.packages",
"com.sun.jersey.samples.https_grizzly.resource;com.sun.jersey.samples.https_grizzly.auth");
// add security filter (which handles http basic authentication)
registration.setInitParameter(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS,
"com.sun.jersey.samples.https_grizzly.auth.SecurityFilter;com.sun.jersey.api.container.filter.LoggingFilter");
registration.setInitParameter(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS,
LoggingFilter.class.getName());
try {
webServer = GrizzlyServerFactory.createHttpServer(
getBaseURI()
);
// start Grizzly embedded server //
System.out.println("Jersey app started. Try out " + BASE_URI + "\nHit CTRL + C to stop it...");
context.deploy(webServer);
webServer.start();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
You are registering a SecurityFilter which takes care of your HTTP basic auth. Enabling logging filter on the server should show basic auth header in the request. Here is an example:
Jan 30, 2013 8:59:00 PM com.sun.jersey.api.container.filter.LoggingFilter filter
INFO: 1 * Server in-bound request
1 > GET http://localhost:8080/context/
1 > host: localhost:8080
1 > connection: keep-alive
1 > cache-control: max-age=0
1 > authorization: Basic dXNlcjpwYXNzd29yZA==
1 > accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
1 > user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17
1 > accept-encoding: gzip,deflate,sdch
1 > accept-language: en-US,en;q=0.8
1 > accept-charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
1 >
Service: GET / User: user
Jan 30, 2013 8:59:00 PM com.sun.jersey.api.container.filter.LoggingFilter$Adapter finish
INFO: 1 * Server out-bound response
1 < 200
1 < Content-Type: text/html
1 <
JERSEY HTTPS EXAMPLE