Basic HTTP authentication with Jersey / Grizzly

前端 未结 3 1324
天命终不由人
天命终不由人 2020-12-09 12:36

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\         


        
相关标签:
3条回答
  • 2020-12-09 12:56

    @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.

    0 讨论(0)
  • 2020-12-09 12:57

    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);
    
    0 讨论(0)
  • 2020-12-09 13:00

    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
    
    0 讨论(0)
提交回复
热议问题