guide extra filter does not bind.

94 views
Skip to first unread message

Rick Coup

unread,
Jun 22, 2018, 1:52:57 PM6/22/18
to google-guice
I am trying to add an extra filter to the existing module. The JWTFilter is added below.
/**
 * Copyright 2016 Netflix, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.netflix.conductor.server;

import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PrivateKey;
import java.util.HashMap;
import java.util.Map;

import javax.inject.Singleton;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.HttpHeaders;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.google.inject.Provides;
import com.sun.jersey.api.core.PackagesResourceConfig;
import com.sun.jersey.api.core.ResourceConfig;
import com.sun.jersey.guice.JerseyServletModule;
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;

import io.jsonwebtoken.Jwts;

import com.netflix.conductor.server.jwt.NotAuthorizedException;

import java.util.logging.Logger;


/**
 * 
 * @author Viren
 *
 */
public final class JerseyModule extends JerseyServletModule {
    @Override
    protected void configureServlets() {

    //checking JWT token on access
    filter("/api/admin/*").through(JWTFilter());
   
    //filter("/*").through(apiOriginFilter());
        
        Map<String, String> jerseyParams = new HashMap<>();
jerseyParams.put("com.sun.jersey.config.feature.FilterForwardOn404", "true");
jerseyParams.put("com.sun.jersey.config.property.WebPageContentRegex", "/(((webjars|api-docs|swagger-ui/docs|manage)/.*)|(favicon\\.ico))");
jerseyParams.put(PackagesResourceConfig.PROPERTY_PACKAGES, "com.netflix.conductor.server.resources;io.swagger.jaxrs.json;io.swagger.jaxrs.listing");
jerseyParams.put(ResourceConfig.FEATURE_DISABLE_WADL, "false");
serve("/api/*").with(GuiceContainer.class, jerseyParams);
    }
    
    @Provides 
@Singleton
public ObjectMapper objectMapper() {
    final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false);
        objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
        objectMapper.setSerializationInclusion(Include.NON_NULL);
        objectMapper.setSerializationInclusion(Include.NON_EMPTY);
    return objectMapper;
}

@Provides 
@Singleton
JacksonJsonProvider jacksonJsonProvider(ObjectMapper mapper) {
    return new JacksonJsonProvider(mapper);
}
@Provides
    @Singleton
    public Filter apiOriginFilter() {
        return new Filter(){

@Override
public void init(FilterConfig filterConfig) throws ServletException {}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        if (!res.containsHeader("Access-Control-Allow-Origin")) {
            res.setHeader("Access-Control-Allow-Origin", "*");
        }
        res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        res.addHeader("Access-Control-Allow-Headers", "Content-Type, api_key, Authorization");
        
        chain.doFilter(request, response);
    }
@Override
public void destroy() {}
       
        };
    }
@Provides
    @Singleton
    public Filter JWTFilter() {
        return new Filter(){

@Override
public void init(FilterConfig filterConfig) throws ServletException {}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

//Assuming the JWT key is stored in the keystore
KeyStore ks=null;
try {
ks = KeyStore.getInstance("JKS");
} catch (KeyStoreException e1) {
// TODO Auto-generated catch block
//e1.printStackTrace();
}
// Get the HTTP Authorization header from the request
        String authorizationHeader = (String) ((HttpServletRequest) request).getHeader(HttpHeaders.AUTHORIZATION);
        //logger.info("#### authorizationHeader : " + authorizationHeader);

        try {
        // Check if the HTTP Authorization header is present and formatted correctly
        if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
           System.out.println("not auth header");
            //logger.severe("#### invalid authorizationHeader : " + authorizationHeader);
            throw new NotAuthorizedException("Not Authorized");
        }
        } catch (Exception e ) {
            
            //logger.info("invalid header");
            //logger.severe("#### invalid authorizationHeader");
        }
        
        // Extract the token from the HTTP Authorization header
        String token = authorizationHeader.substring("Bearer".length()).trim();

        try {

            // Validate the token
            PrivateKey privateKey = (PrivateKey) ks.getKey("jwtkey", "".toCharArray());
            Jwts.parser().setSigningKey(privateKey).parseClaimsJws(token);
            //logger.info("#### valid token : " + token);

        } catch (Exception e) {
            //logger.severe("#### invalid token : " + token);
            //requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
        }
    
        
        chain.doFilter(request, response);
    }
@Override
public void destroy() {}
       
        };
    }
    @Override
    public boolean equals(Object obj) {
        return obj != null && getClass().equals(obj.getClass());
    }

    @Override
    public int hashCode() {
        return getClass().hashCode();
    }


}


The line below and it's associated filter was added by me
     filter("/api/admin/*").through(JWTFilter());
But I got the error:

Exception in thread "main" com.google.inject.CreationException: Unable to create injector, see the following errors:


1) A binding to javax.servlet.Filter was already configured at com.netflix.conductor.server.JerseyModule.apiOriginFilter() (via modules: com.netflix.conductor.server.ServerModule -> com.netflix.conductor.server.JerseyModule).

  at com.netflix.conductor.server.JerseyModule.JWTFilter(JerseyModule.java:122) (via modules: com.netflix.conductor.server.ServerModule -> com.netflix.conductor.server.JerseyModule)


1 error

at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:470)

at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:155)

at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:107)

at com.google.inject.Guice.createInjector(Guice.java:99)

at com.google.inject.Guice.createInjector(Guice.java:73)

at com.google.inject.Guice.createInjector(Guice.java:62)

at com.netflix.conductor.server.ConductorServer.start(ConductorServer.java:207)

at com.netflix.conductor.server.Main.main(Main.java:54)


Any thought?

Thomas Broyer

unread,
Jun 22, 2018, 5:07:04 PM6/22/18
to google-guice
If you explicitly call the JWTFilter() method, then don't annotate it with `@Provides`.

The error is that you have more than one bindings for the Filter class with no qualifier annotation, and not providing into a set (multibinding); but you don't actually need those bindings.

Rick Coup

unread,
Jun 22, 2018, 6:56:19 PM6/22/18
to google-guice
Thanks Tom, you nailed it.
Reply all
Reply to author
Forward
0 new messages