Пример #1
0
  private boolean processWWWAuthChallenge(final HttpMethod method)
      throws MalformedChallengeException, AuthenticationException {
    AuthState authstate = method.getHostAuthState();
    Map challenges =
        AuthChallengeParser.parseChallenges(method.getResponseHeaders(WWW_AUTH_CHALLENGE));
    if (challenges.isEmpty()) {
      LOG.debug("Authentication challenge(s) not found");
      return false;
    }
    AuthScheme authscheme = null;
    try {
      authscheme = this.authProcessor.processChallenge(authstate, challenges);
    } catch (AuthChallengeException e) {
      if (LOG.isWarnEnabled()) {
        LOG.warn(e.getMessage());
      }
    }
    if (authscheme == null) {
      return false;
    }
    String host = method.getParams().getVirtualHost();
    if (host == null) {
      host = conn.getHost();
    }
    int port = conn.getPort();
    AuthScope authscope =
        new AuthScope(host, port, authscheme.getRealm(), authscheme.getSchemeName());

    if (LOG.isDebugEnabled()) {
      LOG.debug("Authentication scope: " + authscope);
    }
    if (authstate.isAuthAttempted() && authscheme.isComplete()) {
      // Already tried and failed
      Credentials credentials = promptForCredentials(authscheme, method.getParams(), authscope);
      if (credentials == null) {
        if (LOG.isInfoEnabled()) {
          LOG.info("Failure authenticating with " + authscope);
        }
        return false;
      } else {
        return true;
      }
    } else {
      authstate.setAuthAttempted(true);
      Credentials credentials = this.state.getCredentials(authscope);
      if (credentials == null) {
        credentials = promptForCredentials(authscheme, method.getParams(), authscope);
      }
      if (credentials == null) {
        if (LOG.isInfoEnabled()) {
          LOG.info("No credentials available for " + authscope);
        }
        return false;
      } else {
        return true;
      }
    }
  }
Пример #2
0
 /**
  * Tests if the {@link HttpMethod method} requires authentication.
  *
  * @param method HTTP method
  * @return boolean <tt>true</tt> if a retry is needed, <tt>false</tt> otherwise.
  */
 private boolean isAuthenticationNeeded(final HttpMethod method) {
   method
       .getHostAuthState()
       .setAuthRequested(method.getStatusCode() == HttpStatus.SC_UNAUTHORIZED);
   method
       .getProxyAuthState()
       .setAuthRequested(method.getStatusCode() == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED);
   if (method.getHostAuthState().isAuthRequested()
       || method.getProxyAuthState().isAuthRequested()) {
     LOG.debug("Authorization required");
     if (method.getDoAuthentication()) { // process authentication response
       return true;
     } else { // let the client handle the authenticaiton
       LOG.info("Authentication requested but doAuthentication is " + "disabled");
       return false;
     }
   } else {
     return false;
   }
 }
Пример #3
0
 private void authenticateHost(final HttpMethod method) throws AuthenticationException {
   // Clean up existing authentication headers
   if (!cleanAuthHeaders(method, WWW_AUTH_RESP)) {
     // User defined authentication header(s) present
     return;
   }
   AuthState authstate = method.getHostAuthState();
   AuthScheme authscheme = authstate.getAuthScheme();
   if (authscheme == null) {
     return;
   }
   if (authstate.isAuthRequested() || !authscheme.isConnectionBased()) {
     String host = method.getParams().getVirtualHost();
     if (host == null) {
       host = conn.getHost();
     }
     int port = conn.getPort();
     AuthScope authscope =
         new AuthScope(host, port, authscheme.getRealm(), authscheme.getSchemeName());
     if (LOG.isDebugEnabled()) {
       LOG.debug("Authenticating with " + authscope);
     }
     Credentials credentials = this.state.getCredentials(authscope);
     if (credentials != null) {
       String authstring = authscheme.authenticate(credentials, method);
       if (authstring != null) {
         method.addRequestHeader(new Header(WWW_AUTH_RESP, authstring, true));
       }
     } else {
       if (LOG.isWarnEnabled()) {
         LOG.warn("Required credentials not available for " + authscope);
         if (method.getHostAuthState().isPreemptive()) {
           LOG.warn(
               "Preemptive authentication requested but no default " + "credentials available");
         }
       }
     }
   }
 }
Пример #4
0
  /**
   * Process the redirect response.
   *
   * @return <code>true</code> if the redirect was successful
   */
  private boolean processRedirectResponse(final HttpMethod method) throws RedirectException {
    // get the location header to find out where to redirect to
    Header locationHeader = method.getResponseHeader("location");
    if (locationHeader == null) {
      // got a redirect response, but no location header
      LOG.error("Received redirect response " + method.getStatusCode() + " but no location header");
      return false;
    }
    String location = locationHeader.getValue();
    if (LOG.isDebugEnabled()) {
      LOG.debug("Redirect requested to location '" + location + "'");
    }

    // rfc2616 demands the location value be a complete URI
    // Location       = "Location" ":" absoluteURI
    URI redirectUri = null;
    URI currentUri = null;

    try {
      currentUri =
          new URI(
              this.conn.getProtocol().getScheme(),
              null,
              this.conn.getHost(),
              this.conn.getPort(),
              method.getPath());

      String charset = method.getParams().getUriCharset();
      redirectUri = new URI(location, true, charset);

      if (redirectUri.isRelativeURI()) {
        if (this.params.isParameterTrue(HttpClientParams.REJECT_RELATIVE_REDIRECT)) {
          LOG.warn("Relative redirect location '" + location + "' not allowed");
          return false;
        } else {
          // location is incomplete, use current values for defaults
          LOG.debug("Redirect URI is not absolute - parsing as relative");
          redirectUri = new URI(currentUri, redirectUri);
        }
      } else {
        // Reset the default params
        method.getParams().setDefaults(this.params);
      }
      method.setURI(redirectUri);
      hostConfiguration.setHost(redirectUri);
    } catch (URIException ex) {
      throw new InvalidRedirectLocationException(
          "Invalid redirect location: " + location, location, ex);
    }

    if (this.params.isParameterFalse(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS)) {
      if (this.redirectLocations == null) {
        this.redirectLocations = new HashSet();
      }
      this.redirectLocations.add(currentUri);
      try {
        if (redirectUri.hasQuery()) {
          redirectUri.setQuery(null);
        }
      } catch (URIException e) {
        // Should never happen
        return false;
      }

      if (this.redirectLocations.contains(redirectUri)) {
        throw new CircularRedirectException("Circular redirect to '" + redirectUri + "'");
      }
    }

    if (LOG.isDebugEnabled()) {
      LOG.debug(
          "Redirecting from '"
              + currentUri.getEscapedURI()
              + "' to '"
              + redirectUri.getEscapedURI());
    }
    // And finally invalidate the actual authentication scheme
    method.getHostAuthState().invalidate();
    return true;
  }
Пример #5
0
  /**
   * Executes the method associated with this method director.
   *
   * @throws IOException
   * @throws HttpException
   */
  public void executeMethod(final HttpMethod method) throws IOException, HttpException {
    if (method == null) {
      throw new IllegalArgumentException("Method may not be null");
    }
    // Link all parameter collections to form the hierarchy:
    // Global -> HttpClient -> HostConfiguration -> HttpMethod
    this.hostConfiguration.getParams().setDefaults(this.params);
    method.getParams().setDefaults(this.hostConfiguration.getParams());

    // Generate default request headers
    Collection defaults =
        (Collection) this.hostConfiguration.getParams().getParameter(HostParams.DEFAULT_HEADERS);
    if (defaults != null) {
      Iterator i = defaults.iterator();
      while (i.hasNext()) {
        method.addRequestHeader((Header) i.next());
      }
    }

    try {
      int maxRedirects = this.params.getIntParameter(HttpClientParams.MAX_REDIRECTS, 100);

      for (int redirectCount = 0; ; ) {

        // make sure the connection we have is appropriate
        if (this.conn != null && !hostConfiguration.hostEquals(this.conn)) {
          this.conn.setLocked(false);
          this.conn.releaseConnection();
          this.conn = null;
        }

        // get a connection, if we need one
        if (this.conn == null) {
          this.conn =
              connectionManager.getConnectionWithTimeout(
                  hostConfiguration, this.params.getConnectionManagerTimeout());
          this.conn.setLocked(true);
          if (this.params.isAuthenticationPreemptive() || this.state.isAuthenticationPreemptive()) {
            LOG.debug("Preemptively sending default basic credentials");
            method.getHostAuthState().setPreemptive();
            method.getHostAuthState().setAuthAttempted(true);
            if (this.conn.isProxied() && !this.conn.isSecure()) {
              method.getProxyAuthState().setPreemptive();
              method.getProxyAuthState().setAuthAttempted(true);
            }
          }
        }
        authenticate(method);
        executeWithRetry(method);
        if (this.connectMethod != null) {
          fakeResponse(method);
          break;
        }

        boolean retry = false;
        if (isRedirectNeeded(method)) {
          if (processRedirectResponse(method)) {
            retry = true;
            ++redirectCount;
            if (redirectCount >= maxRedirects) {
              LOG.error("Narrowly avoided an infinite loop in execute");
              throw new RedirectException("Maximum redirects (" + maxRedirects + ") exceeded");
            }
            if (LOG.isDebugEnabled()) {
              LOG.debug("Execute redirect " + redirectCount + " of " + maxRedirects);
            }
          }
        }
        if (isAuthenticationNeeded(method)) {
          if (processAuthenticationResponse(method)) {
            LOG.debug("Retry authentication");
            retry = true;
          }
        }
        if (!retry) {
          break;
        }
        // retry - close previous stream.  Caution - this causes
        // responseBodyConsumed to be called, which may also close the
        // connection.
        if (method.getResponseBodyAsStream() != null) {
          method.getResponseBodyAsStream().close();
        }
      } // end of retry loop
    } finally {
      if (this.conn != null) {
        this.conn.setLocked(false);
      }
      // If the response has been fully processed, return the connection
      // to the pool.  Use this flag, rather than other tests (like
      // responseStream == null), as subclasses, might reset the stream,
      // for example, reading the entire response into a file and then
      // setting the file as the stream.
      if ((releaseConnection || method.getResponseBodyAsStream() == null) && this.conn != null) {
        this.conn.releaseConnection();
      }
    }
  }