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