Пример #1
0
 public boolean checkCorsPreflight(Request request, Response response) {
   log.finer("checkCorsPreflight " + request.getRequestURI());
   if (!request.getMethod().equalsIgnoreCase("OPTIONS")) {
     log.finer("checkCorsPreflight: not options ");
     return false;
   }
   if (request.getHeader("Origin") == null) {
     log.finer("checkCorsPreflight: no origin header");
     return false;
   }
   log.finer("Preflight request returning");
   response.setStatus(HttpServletResponse.SC_OK);
   String origin = request.getHeader("Origin");
   response.setHeader("Access-Control-Allow-Origin", origin);
   response.setHeader("Access-Control-Allow-Credentials", "true");
   String requestMethods = request.getHeader("Access-Control-Request-Method");
   if (requestMethods != null) {
     if (deployment.getCorsAllowedMethods() != null) {
       requestMethods = deployment.getCorsAllowedMethods();
     }
     response.setHeader("Access-Control-Allow-Methods", requestMethods);
   }
   String allowHeaders = request.getHeader("Access-Control-Request-Headers");
   if (allowHeaders != null) {
     if (deployment.getCorsAllowedHeaders() != null) {
       allowHeaders = deployment.getCorsAllowedHeaders();
     }
     response.setHeader("Access-Control-Allow-Headers", allowHeaders);
   }
   if (deployment.getCorsMaxAge() > -1) {
     response.setHeader("Access-Control-Max-Age", Integer.toString(deployment.getCorsMaxAge()));
   }
   return true;
 }
  @Test
  public final void testRequestUrlIgnorePatternIsUsedIfPrimaryMemcachedNodeIsOperational()
      throws IOException, ServletException {
    when(_memcachedNodesManager.isNodeAvailable(PRIMARY_NODE_IDENTIFIER)).thenReturn(true);
    when(_request.getRequestURI()).thenReturn("/pixel.gif");
    _sessionTrackerValve.invoke(_request, _response);

    verify(_request).setNote(REQUEST_IGNORED, Boolean.TRUE);
  }
  @Test
  public final void testRequestFinishedShouldBeInvokedForIgnoredResources()
      throws IOException, ServletException {
    when(_request.getRequestedSessionId()).thenReturn("foo");
    when(_request.getRequestURI()).thenReturn("/pixel.gif");

    _sessionTrackerValve.invoke(_request, _response);

    verify(_service).requestFinished(eq("foo"), anyString());
  }
  /**
   * Handle the HTTP status code (and corresponding message) generated while processing the
   * specified Request to produce the specified Response. Any exceptions that occur during
   * generation of the error report are logged and swallowed.
   *
   * @param request The request being processed
   * @param response The response being generated
   */
  private void status(Request request, Response response) {

    int statusCode = response.getStatus();

    // Handle a custom error page for this status code
    Context context = request.getContext();
    if (context == null) return;

    /* Only look for error pages when isError() is set.
     * isError() is set when response.sendError() is invoked. This
     * allows custom error pages without relying on default from
     * web.xml.
     */
    if (!response.isError()) return;

    ErrorPage errorPage = context.findErrorPage(statusCode);
    if (errorPage == null) {
      // Look for a default error page
      errorPage = context.findErrorPage(0);
    }
    if (errorPage != null && response.setErrorReported()) {
      response.setAppCommitted(false);
      request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, Integer.valueOf(statusCode));

      String message = response.getMessage();
      if (message == null) message = "";
      request.setAttribute(RequestDispatcher.ERROR_MESSAGE, message);
      request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, errorPage.getLocation());
      request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ERROR);

      Wrapper wrapper = request.getWrapper();
      if (wrapper != null)
        request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME, wrapper.getName());
      request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI());
      if (custom(request, response, errorPage)) {
        try {
          response.finishResponse();
        } catch (ClientAbortException e) {
          // Ignore
        } catch (IOException e) {
          container.getLogger().warn("Exception Processing " + errorPage, e);
        }
      }
    }
  }
 /**
  * /** When we do GET call for WSDL/WADL, we do not want to authenticate/throttle the request.
  *
  * <p>TODO check logic
  *
  * @param request
  * @param response
  * @param compositeValve
  * @param context
  */
 private void handleWSDLGetRequest(
     Request request, Response response, CompositeValve compositeValve, String context) {
   if (request.getMethod().equals(Constants.Configuration.HTTP_METHOD_GET)) {
     // TODO:Need to get these paths from a config file.
     if (request.getRequestURI().matches(context + "/[^/]*/services")) {
       getNext().invoke(request, response, compositeValve);
       return;
     }
     Enumeration<String> params = request.getParameterNames();
     String paramName = null;
     while (params.hasMoreElements()) {
       paramName = params.nextElement();
       if (paramName.endsWith("wsdl") || paramName.endsWith("wadl")) {
         getNext().invoke(request, response, compositeValve);
         return;
       }
     }
   }
 }
  @BeforeMethod
  public void setUp() throws Exception {
    _service = mock(MemcachedSessionService.class);
    _request = mock(Request.class);
    _response = mock(Response.class);

    final Context _contextContainer = mock(Context.class);
    final Host _hostContainer = mock(Host.class);
    final SessionManager _manager = mock(SessionManager.class);

    when(_service.getManager()).thenReturn(_manager);
    when(_manager.getContainer()).thenReturn(_contextContainer);
    when(_contextContainer.getParent()).thenReturn(_hostContainer);
    when(_contextContainer.getPath()).thenReturn("/");

    _sessionTrackerValve = createSessionTrackerValve();
    _nextValve = mock(Valve.class);
    _sessionTrackerValve.setNext(_nextValve);
    _sessionTrackerValve.setContainer(_hostContainer);
    _memcachedNodesManager = mock(MemcachedNodesManager.class);
    _sessionIdFormat = mock(SessionIdFormat.class);

    when(_request.getRequestURI()).thenReturn("/someRequest");
    when(_request.getMethod()).thenReturn("GET");
    when(_request.getQueryString()).thenReturn(null);
    when(_request.getContext()).thenReturn(_contextContainer);

    when(_request.getNote(eq(RequestTrackingHostValve.REQUEST_PROCESSED))).thenReturn(Boolean.TRUE);
    when(_request.getNote(eq(RequestTrackingHostValve.SESSION_ID_CHANGED)))
        .thenReturn(Boolean.FALSE);

    when(_sessionIdFormat.extractMemcachedId(anyString())).thenReturn(PRIMARY_NODE_IDENTIFIER);
    when(_service.getMemcachedNodesManager()).thenReturn(_memcachedNodesManager);
    when(_memcachedNodesManager.isNodeAvailable(PRIMARY_NODE_IDENTIFIER))
        .thenReturn(IS_PRIMARY_MEMCACHED_NODE_OPERATIONAL);
    when(_memcachedNodesManager.getSessionIdFormat()).thenReturn(_sessionIdFormat);
  }
Пример #7
0
  /**
   * Log the interesting request parameters, invoke the next Valve in the sequence, and log the
   * interesting response parameters.
   *
   * @param request The servlet request to be processed
   * @param response The servlet response to be created
   * @exception IOException if an input/output error occurs
   * @exception ServletException if a servlet error occurs
   */
  public void invoke(Request request, Response response) throws IOException, ServletException {

    Log log = container.getLogger();

    // Log pre-service information
    log.info("REQUEST URI       =" + request.getRequestURI());
    log.info("          authType=" + request.getAuthType());
    log.info(" characterEncoding=" + request.getCharacterEncoding());
    log.info("     contentLength=" + request.getContentLength());
    log.info("       contentType=" + request.getContentType());
    log.info("       contextPath=" + request.getContextPath());
    Cookie cookies[] = request.getCookies();
    if (cookies != null) {
      for (int i = 0; i < cookies.length; i++)
        log.info("            cookie=" + cookies[i].getName() + "=" + cookies[i].getValue());
    }
    Enumeration hnames = request.getHeaderNames();
    while (hnames.hasMoreElements()) {
      String hname = (String) hnames.nextElement();
      Enumeration hvalues = request.getHeaders(hname);
      while (hvalues.hasMoreElements()) {
        String hvalue = (String) hvalues.nextElement();
        log.info("            header=" + hname + "=" + hvalue);
      }
    }
    log.info("            locale=" + request.getLocale());
    log.info("            method=" + request.getMethod());
    Enumeration pnames = request.getParameterNames();
    while (pnames.hasMoreElements()) {
      String pname = (String) pnames.nextElement();
      String pvalues[] = request.getParameterValues(pname);
      StringBuffer result = new StringBuffer(pname);
      result.append('=');
      for (int i = 0; i < pvalues.length; i++) {
        if (i > 0) result.append(", ");
        result.append(pvalues[i]);
      }
      log.info("         parameter=" + result.toString());
    }
    log.info("          pathInfo=" + request.getPathInfo());
    log.info("          protocol=" + request.getProtocol());
    log.info("       queryString=" + request.getQueryString());
    log.info("        remoteAddr=" + request.getRemoteAddr());
    log.info("        remoteHost=" + request.getRemoteHost());
    log.info("        remoteUser="******"requestedSessionId=" + request.getRequestedSessionId());
    log.info("            scheme=" + request.getScheme());
    log.info("        serverName=" + request.getServerName());
    log.info("        serverPort=" + request.getServerPort());
    log.info("       servletPath=" + request.getServletPath());
    log.info("          isSecure=" + request.isSecure());
    log.info("---------------------------------------------------------------");

    // Perform the request
    getNext().invoke(request, response);

    // Log post-service information
    log.info("---------------------------------------------------------------");
    log.info("          authType=" + request.getAuthType());
    log.info("     contentLength=" + response.getContentLength());
    log.info("       contentType=" + response.getContentType());
    Cookie rcookies[] = response.getCookies();
    for (int i = 0; i < rcookies.length; i++) {
      log.info(
          "            cookie="
              + rcookies[i].getName()
              + "="
              + rcookies[i].getValue()
              + "; domain="
              + rcookies[i].getDomain()
              + "; path="
              + rcookies[i].getPath());
    }
    String rhnames[] = response.getHeaderNames();
    for (int i = 0; i < rhnames.length; i++) {
      String rhvalues[] = response.getHeaderValues(rhnames[i]);
      for (int j = 0; j < rhvalues.length; j++)
        log.info("            header=" + rhnames[i] + "=" + rhvalues[j]);
    }
    log.info("           message=" + response.getMessage());
    log.info("        remoteUser="******"            status=" + response.getStatus());
    log.info("===============================================================");
  }
  public void invoke(Request request, Response response, CompositeValve compositeValve) {

    if (authenticator == null) {
      authenticator = new APITokenAuthenticator();
    }

    String context = request.getContextPath();
    if (context == null || context.equals("")) {
      // Invoke next valve in pipe.
      getNext().invoke(request, response, compositeValve);
      return;
    }

    // todo remove version from context - special case for apps
    //        context = stripVersionfromContext(context);

    boolean contextExist;
    Boolean contextValueInCache = null;
    if (APIUtil.getAPIContextCache().get(context) != null) {
      contextValueInCache =
          Boolean.parseBoolean(APIUtil.getAPIContextCache().get(context).toString());
    }

    if (contextValueInCache != null) {
      contextExist = contextValueInCache;
    } else {
      contextExist = ApiMgtDAO.isContextExist(context);
      APIUtil.getAPIContextCache().put(context, contextExist);
    }

    if (!contextExist) {
      getNext().invoke(request, response, compositeValve);
      return;
    }

    handleWSDLGetRequest(request, response, compositeValve, context);

    String dispatcherPath = null;
    boolean forwardingRequired = false;

    long requestTime = System.currentTimeMillis();
    APIManagerInterceptorOps interceptorOps = new APIManagerInterceptorOps();
    UsageStatConfiguration statConfiguration = new UsageStatConfiguration();
    if (contextExist) {
      // Use embedded API Management
      if (log.isDebugEnabled()) {
        log.debug("API Manager Interceptor Valve Got invoked!!");
      }

      String bearerToken = request.getHeader(APIConstants.OperationParameter.AUTH_PARAM_NAME);
      String accessToken = null;

      /* Authenticate*/
      try {
        if (bearerToken != null) {
          accessToken = APIManagetInterceptorUtils.getBearerToken(bearerToken);
        } else {
          // There can be some API published with None Auth Type
          /*
           * throw new
           * APIFaultException(APIConstants.KeyValidationStatus
           * .API_AUTH_INVALID_CREDENTIALS,
           * "Invalid format for Authorization header. Expected 'Bearer <token>'"
           * );
           */
        }

        String apiVersion = APIManagetInterceptorUtils.getAPIVersion(request);
        dispatcherPath = apiVersion;
        // todo get proper version
        // handling version for web-application API mgmt

        if (!APIManagerInterceptorConstant.DEFAULT_API_VERSION.equals(apiVersion)
            || "".equals(apiVersion)) {
          apiVersion = APIManagerInterceptorConstant.DEFAULT_API_VERSION;
        } else {
          forwardingRequired = true;
        }

        String domain = request.getHeader(APITokenValidator.getAPIManagerClientDomainHeader());
        String authLevel =
            authenticator.getResourceAuthenticationScheme(
                context, apiVersion, request.getRequestURI(), request.getMethod());
        if (authLevel.equals(APIConstants.NO_MATCHING_AUTH_SCHEME)) {
          APIManagetInterceptorUtils.handleNoMatchAuthSchemeCallForRestService(
              response, request.getMethod(), request.getRequestURI(), apiVersion, context);
          return;
        } else {
          interceptorOps.doAuthenticate(
              context,
              APIConstants.DEFAULT_VERSION_PREFIX + apiVersion,
              accessToken,
              authLevel,
              domain);
        }
      } catch (APIManagementException e) {
        // ignore
      } catch (APIFaultException e) {
          /* If !isAuthorized APIFaultException is thrown*/
        APIManagetInterceptorUtils.handleAPIFaultForRestService(
            e,
            APIManagerErrorConstants.API_SECURITY_NS,
            APIManagerErrorConstants.API_SECURITY_NS_PREFIX,
            response);
        return;
      }
      /* Throttle*/
      try {
        interceptorOps.doThrottle(request, accessToken);
      } catch (APIFaultException e) {
        APIManagetInterceptorUtils.handleAPIFaultForRestService(
            e,
            APIManagerErrorConstants.API_THROTTLE_NS,
            APIManagerErrorConstants.API_THROTTLE_NS_PREFIX,
            response);
        return;
      }
      /* Publish Statistic if enabled*/
      if (statConfiguration.isStatsPublishingEnabled()) {
        try {
          interceptorOps.publishStatistics(request, requestTime, false);
        } catch (APIManagementException e) {
          log.error("Error occurred when publishing stats", e);
        }
      }
    }

    if (forwardingRequired) {
      try {
        request
            .getRequestDispatcher(
                request.getContextPath() + "/services/customers/customerservice/customers/123")
            .forward(request, response);
        //                response.sendRedirect(request.getContextPath() +
        // "/services/customers/customerservice/customers/123");
        //                return;
      } catch (ServletException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    // Invoke next valve in pipe.
    getNext().invoke(request, response, compositeValve);

    // Handle Responses
    if (contextExist && statConfiguration.isStatsPublishingEnabled()) {
      try {
        interceptorOps.publishStatistics(request, requestTime, true);
      } catch (APIManagementException e) {
        log.error("Error occurred when publishing stats", e);
      }
    }
  }
  /**
   * Handle the specified Throwable encountered while processing the specified Request to produce
   * the specified Response. Any exceptions that occur during generation of the exception report are
   * logged and swallowed.
   *
   * @param request The request being processed
   * @param response The response being generated
   * @param throwable The exception that occurred (which possibly wraps a root cause exception
   */
  protected void throwable(Request request, Response response, Throwable throwable) {
    Context context = request.getContext();
    if (context == null) return;

    Throwable realError = throwable;

    if (realError instanceof ServletException) {
      realError = ((ServletException) realError).getRootCause();
      if (realError == null) {
        realError = throwable;
      }
    }

    // If this is an aborted request from a client just log it and return
    if (realError instanceof ClientAbortException) {
      if (log.isDebugEnabled()) {
        log.debug(sm.getString("standardHost.clientAbort", realError.getCause().getMessage()));
      }
      return;
    }

    ErrorPage errorPage = findErrorPage(context, throwable);
    if ((errorPage == null) && (realError != throwable)) {
      errorPage = findErrorPage(context, realError);
    }

    if (errorPage != null) {
      if (response.setErrorReported()) {
        response.setAppCommitted(false);
        request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, errorPage.getLocation());
        request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, DispatcherType.ERROR);
        request.setAttribute(
            RequestDispatcher.ERROR_STATUS_CODE,
            new Integer(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
        request.setAttribute(RequestDispatcher.ERROR_MESSAGE, throwable.getMessage());
        request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, realError);
        Wrapper wrapper = request.getWrapper();
        if (wrapper != null)
          request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME, wrapper.getName());
        request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI());
        request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE, realError.getClass());
        if (custom(request, response, errorPage)) {
          try {
            response.finishResponse();
          } catch (IOException e) {
            container.getLogger().warn("Exception Processing " + errorPage, e);
          }
        }
      }
    } else {
      // A custom error-page has not been defined for the exception
      // that was thrown during request processing. Check if an
      // error-page for error code 500 was specified and if so,
      // send that page back as the response.
      response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      // The response is an error
      response.setError();

      status(request, response);
    }
  }
  /**
   * Select the appropriate child Context to process this request, based on the specified request
   * URI. If no matching Context can be found, return an appropriate HTTP error.
   *
   * @param request Request to be processed
   * @param response Response to be produced
   * @exception IOException if an input/output error occurred
   * @exception ServletException if a servlet error occurred
   */
  @Override
  public final void invoke(Request request, Response response)
      throws IOException, ServletException {

    /*
     * xujb:
     * 和Engine一样,调用下层的context,让它来做一些处理
     * 自身也处理了一些的逻辑
     *
     * */

    // Select the Context to be used for this Request
    Context context = request.getContext();
    if (context == null) {
      response.sendError(
          HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm.getString("standardHost.noContext"));
      return;
    }

    // Bind the context CL to the current thread
    if (context.getLoader() != null) {
      // Not started - it should check for availability first
      // This should eventually move to Engine, it's generic.
      if (Globals.IS_SECURITY_ENABLED) {
        PrivilegedAction<Void> pa = new PrivilegedSetTccl(context.getLoader().getClassLoader());
        AccessController.doPrivileged(pa);
      } else {
        Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());
      }
    }
    if (request.isAsyncSupported()) {
      request.setAsyncSupported(context.getPipeline().isAsyncSupported());
    }

    boolean asyncAtStart = request.isAsync();
    boolean asyncDispatching = request.isAsyncDispatching();
    if (asyncAtStart || context.fireRequestInitEvent(request)) {

      // Ask this Context to process this request. Requests that are in
      // async mode and are not being dispatched to this resource must be
      // in error and have been routed here to check for application
      // defined error pages.
      try {
        if (!asyncAtStart || asyncDispatching) {
          context.getPipeline().getFirst().invoke(request, response);
        } else {
          // Make sure this request/response is here because an error
          // report is required.
          if (!response.isErrorReportRequired()) {
            throw new IllegalStateException(sm.getString("standardHost.asyncStateError"));
          }
        }
      } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        // If a new error occurred while trying to report a previous
        // error simply log the new error and allow the original error
        // to be reported.
        if (response.isErrorReportRequired()) {
          container.getLogger().error("Exception Processing " + request.getRequestURI(), t);
        } else {
          request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
          throwable(request, response, t);
        }
      }

      // Now that the request/response pair is back under container
      // control lift the suspension so that the error handling can
      // complete and/or the container can flush any remaining data
      response.setSuspended(false);

      Throwable t = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);

      // Protect against NPEs if the context was destroyed during a
      // long running request.
      if (!context.getState().isAvailable()) {
        return;
      }

      // Look for (and render if found) an application level error page
      if (response.isErrorReportRequired()) {
        if (t != null) {
          throwable(request, response, t);
        } else {
          status(request, response);
        }
      }

      if (!request.isAsync() && (!asyncAtStart || !response.isErrorReportRequired())) {
        context.fireRequestDestroyEvent(request);
      }
    }

    // Access a session (if present) to update last accessed time, based on a
    // strict interpretation of the specification
    if (ACCESS_SESSION) {
      request.getSession(false);
    }

    // Restore the context classloader
    if (Globals.IS_SECURITY_ENABLED) {
      PrivilegedAction<Void> pa = new PrivilegedSetTccl(StandardHostValve.class.getClassLoader());
      AccessController.doPrivileged(pa);
    } else {
      Thread.currentThread().setContextClassLoader(StandardHostValve.class.getClassLoader());
    }
  }
  public void invoke(Request request, Response response, CompositeValve compositeValve) {

    String context = request.getContextPath();
    if (context == null || context.equals("")) {
      // Invoke next valve in pipe.
      getNext().invoke(request, response, compositeValve);
      return;
    }

    boolean contextExist;
    Boolean contextValueInCache = null;
    if (APIUtil.getAPIContextCache().get(context) != null) {
      contextValueInCache =
          Boolean.parseBoolean(APIUtil.getAPIContextCache().get(context).toString());
    }

    if (contextValueInCache != null) {
      contextExist = contextValueInCache;
    } else {
      contextExist = ApiMgtDAO.isContextExist(context);
      APIUtil.getAPIContextCache().put(context, contextExist);
    }

    if (!contextExist) {
      getNext().invoke(request, response, compositeValve);
      return;
    }

    handleWSDLGetRequest(request, response, compositeValve, context);

    long requestTime = System.currentTimeMillis();
    APIManagerInterceptorOps interceptorOps = new APIManagerInterceptorOps();
    UsageStatConfiguration statConfiguration = new UsageStatConfiguration();
    if (contextExist) {
      // Use embedded WebApp Management
      if (log.isDebugEnabled()) {
        log.debug("WebApp Manager Interceptor Valve Got invoked!!");
      }

      String bearerToken = request.getHeader(APIConstants.OperationParameter.AUTH_PARAM_NAME);
      String accessToken = null;

      /* Authenticate*/
      try {
        if (bearerToken != null) {
          accessToken = APIManagetInterceptorUtils.getBearerToken(bearerToken);
        } else {
          // There can be some WebApp published with None Auth Type
          /*
           * throw new
           * APIFaultException(APIConstants.KeyValidationStatus
           * .API_AUTH_INVALID_CREDENTIALS,
           * "Invalid format for Authorization header. Expected 'Bearer <token>'"
           * );
           */
        }

        String apiVersion = APIManagetInterceptorUtils.getAPIVersion(request);
        String domain = request.getHeader(APITokenValidator.getAPIManagerClientDomainHeader());
        String authLevel =
            authenticator.getResourceAuthenticationScheme(
                context, apiVersion, request.getRequestURI(), request.getMethod());
        if (authLevel == APIConstants.NO_MATCHING_AUTH_SCHEME) {
          APIManagetInterceptorUtils.handleNoMatchAuthSchemeCallForRestService(
              response, request.getMethod(), request.getRequestURI(), apiVersion, context);
          return;
        } else {
          interceptorOps.doAuthenticate(context, apiVersion, accessToken, authLevel, domain);
        }
      } catch (APIManagementException e) {
        // ignore
      } catch (APIFaultException e) {
          /* If !isAuthorized APIFaultException is thrown*/
        APIManagetInterceptorUtils.handleAPIFaultForRestService(
            e,
            APIManagerErrorConstants.API_SECURITY_NS,
            APIManagerErrorConstants.API_SECURITY_NS_PREFIX,
            response);
        return;
      }
      /* Throttle*/
      try {
        interceptorOps.doThrottle(request, accessToken);
      } catch (APIFaultException e) {
        APIManagetInterceptorUtils.handleAPIFaultForRestService(
            e,
            APIManagerErrorConstants.API_THROTTLE_NS,
            APIManagerErrorConstants.API_THROTTLE_NS_PREFIX,
            response);
        return;
      }
      /* Publish Statistic if enabled*/
      if (statConfiguration.isStatsPublishingEnabled()) {
        try {
          interceptorOps.publishStatistics(request, requestTime, false);
        } catch (APIManagementException e) {
          log.error("Error occured when publishing stats", e);
        }
      }
    }

    // Invoke next valve in pipe.
    getNext().invoke(request, response, compositeValve);

    // Handle Responses
    if (contextExist && statConfiguration.isStatsPublishingEnabled()) {
      try {
        interceptorOps.publishStatistics(request, requestTime, true);
      } catch (APIManagementException e) {
        log.error("Error occured when publishing stats", e);
      }
    }
  }
  /**
   * Enforce any user data constraint required by the security constraint guarding this request URI.
   * Return <code>true</code> if this constraint was not violated and processing should continue, or
   * <code>false</code> if we have created a response already.
   *
   * @param request Request we are processing
   * @param response Response we are creating
   * @param constraints Security constraint being checked
   * @exception IOException if an input/output error occurs
   */
  @Override
  public boolean hasUserDataPermission(
      Request request, Response response, SecurityConstraint[] constraints) throws IOException {

    // Is there a relevant user data constraint?
    if (constraints == null || constraints.length == 0) {
      if (log.isDebugEnabled()) log.debug("  No applicable security constraint defined");
      return (true);
    }
    for (int i = 0; i < constraints.length; i++) {
      SecurityConstraint constraint = constraints[i];
      String userConstraint = constraint.getUserConstraint();
      if (userConstraint == null) {
        if (log.isDebugEnabled()) log.debug("  No applicable user data constraint defined");
        return (true);
      }
      if (userConstraint.equals(Constants.NONE_TRANSPORT)) {
        if (log.isDebugEnabled()) log.debug("  User data constraint has no restrictions");
        return (true);
      }
    }
    // Validate the request against the user data constraint
    if (request.getRequest().isSecure()) {
      if (log.isDebugEnabled()) log.debug("  User data constraint already satisfied");
      return (true);
    }
    // Initialize variables we need to determine the appropriate action
    int redirectPort = request.getConnector().getRedirectPort();

    // Is redirecting disabled?
    if (redirectPort <= 0) {
      if (log.isDebugEnabled()) log.debug("  SSL redirect is disabled");
      response.sendError(HttpServletResponse.SC_FORBIDDEN, request.getRequestURI());
      return (false);
    }

    // Redirect to the corresponding SSL port
    StringBuilder file = new StringBuilder();
    String protocol = "https";
    String host = request.getServerName();
    // Protocol
    file.append(protocol).append("://").append(host);
    // Host with port
    if (redirectPort != 443) {
      file.append(":").append(redirectPort);
    }
    // URI
    file.append(request.getRequestURI());
    String requestedSessionId = request.getRequestedSessionId();
    if ((requestedSessionId != null) && request.isRequestedSessionIdFromURL()) {
      file.append(";");
      file.append(SessionConfig.getSessionUriParamName(request.getContext()));
      file.append("=");
      file.append(requestedSessionId);
    }
    String queryString = request.getQueryString();
    if (queryString != null) {
      file.append('?');
      file.append(queryString);
    }
    if (log.isDebugEnabled()) log.debug("  Redirecting to " + file.toString());
    response.sendRedirect(file.toString());
    return (false);
  }
    public boolean validate(Request request) {
      if ((userName == null)
          || (realmName == null)
          || (nonce == null)
          || (uri == null)
          || (response == null)) {
        return false;
      }

      // Validate the URI - should match the request line sent by client
      if (validateUri) {
        String uriQuery;
        String query = request.getQueryString();
        if (query == null) {
          uriQuery = request.getRequestURI();
        } else {
          uriQuery = request.getRequestURI() + "?" + query;
        }
        if (!uri.equals(uriQuery)) {
          // Some clients (older Android) use an absolute URI for
          // DIGEST but a relative URI in the request line.
          // request. 2.3.5 < fixed Android version <= 4.0.3
          String host = request.getHeader("host");
          String scheme = request.getScheme();
          if (host != null && !uriQuery.startsWith(scheme)) {
            StringBuilder absolute = new StringBuilder();
            absolute.append(scheme);
            absolute.append("://");
            absolute.append(host);
            absolute.append(uriQuery);
            if (!uri.equals(absolute.toString())) {
              return false;
            }
          } else {
            return false;
          }
        }
      }

      // Validate the Realm name
      String lcRealm = getRealmName(request.getContext());
      if (!lcRealm.equals(realmName)) {
        return false;
      }

      // Validate the opaque string
      if (!opaque.equals(opaqueReceived)) {
        return false;
      }

      // Validate nonce
      int i = nonce.indexOf(":");
      if (i < 0 || (i + 1) == nonce.length()) {
        return false;
      }
      long nonceTime;
      try {
        nonceTime = Long.parseLong(nonce.substring(0, i));
      } catch (NumberFormatException nfe) {
        return false;
      }
      String md5clientIpTimeKey = nonce.substring(i + 1);
      long currentTime = System.currentTimeMillis();
      if ((currentTime - nonceTime) > nonceValidity) {
        nonceStale = true;
        synchronized (nonces) {
          nonces.remove(nonce);
        }
      }
      String serverIpTimeKey = request.getRemoteAddr() + ":" + nonceTime + ":" + key;
      byte[] buffer =
          ConcurrentMessageDigest.digestMD5(serverIpTimeKey.getBytes(StandardCharsets.ISO_8859_1));
      String md5ServerIpTimeKey = MD5Encoder.encode(buffer);
      if (!md5ServerIpTimeKey.equals(md5clientIpTimeKey)) {
        return false;
      }

      // Validate qop
      if (qop != null && !QOP.equals(qop)) {
        return false;
      }

      // Validate cnonce and nc
      // Check if presence of nc and Cnonce is consistent with presence of qop
      if (qop == null) {
        if (cnonce != null || nc != null) {
          return false;
        }
      } else {
        if (cnonce == null || nc == null) {
          return false;
        }
        // RFC 2617 says nc must be 8 digits long. Older Android clients
        // use 6. 2.3.5 < fixed Android version <= 4.0.3
        if (nc.length() < 6 || nc.length() > 8) {
          return false;
        }
        long count;
        try {
          count = Long.parseLong(nc, 16);
        } catch (NumberFormatException nfe) {
          return false;
        }
        NonceInfo info;
        synchronized (nonces) {
          info = nonces.get(nonce);
        }
        if (info == null) {
          // Nonce is valid but not in cache. It must have dropped out
          // of the cache - force a re-authentication
          nonceStale = true;
        } else {
          if (!info.nonceCountValid(count)) {
            return false;
          }
        }
      }
      return true;
    }