Basic HTTP authentication with Jersey / Grizzly
Solution 1
I managed to get it working after a couple of hours, based on this blog post.
My solution involves:
- Maven artifacts:
- jersey-server (v 1.17)
- jersey-grizzly2 (v 1.17)
- Hard coded username / password (replace with database lookup if you like)
- No web.xml (programatically configured server)
- No SSL involved
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);
Solution 2
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
aioobe
Previously: Senior Member of Technical Staff at Oracle, developing the java compiler. Cheering for this one right now: What is the difference between public, protected, package-private and private in Java? Most popular: Why is executing Java code in comments with certain Unicode characters allowed? How can I convert byte size into a human-readable format in Java? (apparently the most copied snippet on Stack Overflow!) Handling InterruptedException in Java For a recent bio, check out my web page, http://aioo.be. My StackRating badge: Also, check out my new web page: Programming.Guide
Updated on July 18, 2022Comments
-
aioobe almost 2 years
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") .port(8081) .build(); ResourceConfig rc = new PackagesResourceConfig("se.aioobe.resources"); HttpServer httpServer = GrizzlyServerFactory.createHttpServer(baseUri, rc);
Now I need to protect the resources using Basic HTTP authentication, and I can't figure out how to do this.
I can switch from Grizzly to for instance Jetty if it is simpler to get it to work, but I really value the simple configuration / start up that Grizzly provides.
I've read a lot of tutorials. They all mention the web.xml but in my current configuration I don't have one. (Do I need to add one for HTTP authentication?) I've found the following questions, neither of them is of any help :-(
(No SSL required at this point. The authentication is at this point just to prevent the public from peeking at our beta.)
TL;DR: How do I add basic HTTP authentication to a Jersey / Grizzly webapp?
-
aioobe over 11 yearsThanks! I did look into that. I couldn't get it to compile, even after installing a bunch of jar-files manually in my mvn repository. I did get it working in the end based on similar code. I'll post an answer in a minute or so.