Authentification HTTP de base avec Jersey / Grizzly

J’ai écrit un serveur REST simple utilisant JAX-RS, Jersey et Grizzly. Voici comment je démarre le serveur:

URI baseUri = UriBuilder.fromUri("http://localhost/api") .port(8081) .build(); ResourceConfig rc = new PackagesResourceConfig("se.aioobe.resources"); HttpServer httpServer = GrizzlyServerFactory.createHttpServer(baseUri, rc); 

Maintenant, je dois protéger les ressources à l’aide de l’authentification HTTP de base et je ne vois pas comment faire.

Par exemple, je peux passer de Grizzly à Jetty s’il est plus simple de le faire fonctionner, mais j’apprécie beaucoup la configuration / démarrage simple fournie par Grizzly.

J’ai lu beaucoup de tutoriels. Ils mentionnent tous le fichier web.xml mais, dans ma configuration actuelle, je n’en ai pas. (Ai-je besoin d’en append un pour l’authentification HTTP?) J’ai trouvé les questions suivantes , aucune d’entre elles n’a aucune aide 🙁

(Aucun SSL n’est requirejs à ce stade. L’authentification a pour but d’empêcher le public de regarder furtivement notre version bêta.)

TL; DR : Comment append une authentification HTTP de base à une application Web Jersey / Grizzly?

J’ai réussi à le faire fonctionner après quelques heures, basé sur ce post de blog .

Ma solution implique:

  • Artefacts Maven:
    • serveur-maillot (v 1.17)
    • jersey-grizzly2 (v 1.17)
  • Nom d’utilisateur / mot de passe codé en dur (remplacez-le par la recherche dans la firebase database si vous le souhaitez)
  • Pas de web.xml (serveur configuré par programme)
  • Pas de SSL impliqué

J’ai créé ce 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. Ssortingng method = containerRequest.getMethod(); Ssortingng path = containerRequest.getPath(true); if (method.equals("GET") && path.equals("application.wadl")) return containerRequest; // Get the authentication passed in HTTP headers parameters Ssortingng auth = containerRequest.getHeaderValue("authorization"); if (auth == null) throw unauthorized; auth = auth.replaceFirst("[Bb]asic ", ""); Ssortingng userColonPass = Base64.base64Decode(auth); if (!userColonPass.equals("admin:toHah1ooMeor6Oht")) throw unauthorized; return containerRequest; } } 

Et j’ai ensuite changé le code de démarrage pour inclure le filtre:

 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", ".AuthFilter"); ////////////////////////////// HttpServer httpServer = GrizzlyServerFactory.createHttpServer(baseUri, rc); 

Vous voudrez peut-être vérifier l’ échantillon Grizzly HTTPS Client Server dissortingbué avec Jersey, qui fait exactement cela. Voici un extrait de cet exemple sur la configuration des filtres de sécurité sur le serveur Grizzly.

  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()); } 

Vous enregistrez un SecurityFilter qui prend en charge votre autorisation HTTP de base. L’activation du filtre de journalisation sur le serveur doit afficher l’en-tête d’authentification de base dans la demande. Voici un exemple:

 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 Sachez que même si cela vous obligera à travailler, vous aurez besoin d’une meilleure vérification des erreurs lorsque vous travaillerez avec l’en-tête. Par exemple:

  auth = auth.replaceFirst("[Bb]asic ", ""); 

Cela suppose que l’en-tête d’authentification est Basic, alors que ce n’est peut-être pas le cas. Vous devriez vérifier que l’en-tête d’autorisation commence par ‘Basic’ et si non jeté non autorisé. Même chose pour s’assurer que le rest des informations est réellement codé en base64.