Search in sources :

Example 1 with Realm

use of org.asynchttpclient.Realm in project async-http-client by AsyncHttpClient.

the class NettyRequestSender method sendRequestWithNewChannel.

private <//
T> //
ListenableFuture<T> sendRequestWithNewChannel(//
Request request, //
ProxyServer proxy, //
NettyResponseFuture<T> future, //
AsyncHandler<T> asyncHandler, boolean performingNextRequest) {
    // some headers are only set when performing the first request
    HttpHeaders headers = future.getNettyRequest().getHttpRequest().headers();
    Realm realm = future.getRealm();
    Realm proxyRealm = future.getProxyRealm();
    requestFactory.addAuthorizationHeader(headers, perConnectionAuthorizationHeader(request, proxy, realm));
    requestFactory.setProxyAuthorizationHeader(headers, perConnectionProxyAuthorizationHeader(request, proxyRealm));
    future.setInAuth(realm != null && realm.isUsePreemptiveAuth() && realm.getScheme() != AuthScheme.NTLM);
    future.setInProxyAuth(proxyRealm != null && proxyRealm.isUsePreemptiveAuth() && proxyRealm.getScheme() != AuthScheme.NTLM);
    // Do not throw an exception when we need an extra connection for a redirect
    // FIXME why? This violate the max connection per host handling, right?
    Bootstrap bootstrap = channelManager.getBootstrap(request.getUri(), proxy);
    Object partitionKey = future.getPartitionKey();
    // we disable channelPreemption when performing next requests
    final boolean acquireChannelLock = !performingNextRequest;
    try {
        // redirect.
        if (acquireChannelLock) {
            // if there's an exception here, channel wasn't preempted and resolve won't happen
            channelManager.acquireChannelLock(partitionKey);
        }
    } catch (Throwable t) {
        abort(null, future, getCause(t));
        // exit and don't try to resolve address
        return future;
    }
    scheduleRequestTimeout(future);
    //
    RequestHostnameResolver.INSTANCE.resolve(request, proxy, asyncHandler).addListener(new SimpleFutureListener<List<InetSocketAddress>>() {

        @Override
        protected void onSuccess(List<InetSocketAddress> addresses) {
            NettyConnectListener<T> connectListener = new NettyConnectListener<>(future, NettyRequestSender.this, channelManager, acquireChannelLock, partitionKey);
            NettyChannelConnector connector = new NettyChannelConnector(request.getLocalAddress(), addresses, asyncHandler, clientState, config);
            if (!future.isDone()) {
                connector.connect(bootstrap, connectListener);
            } else if (acquireChannelLock) {
                channelManager.releaseChannelLock(partitionKey);
            }
        }

        @Override
        protected void onFailure(Throwable cause) {
            if (acquireChannelLock) {
                channelManager.releaseChannelLock(partitionKey);
            }
            abort(null, future, getCause(cause));
        }
    });
    return future;
}
Also used : HttpHeaders(io.netty.handler.codec.http.HttpHeaders) DefaultHttpHeaders(io.netty.handler.codec.http.DefaultHttpHeaders) InetSocketAddress(java.net.InetSocketAddress) Bootstrap(io.netty.bootstrap.Bootstrap) List(java.util.List) NettyConnectListener(org.asynchttpclient.netty.channel.NettyConnectListener) Realm(org.asynchttpclient.Realm)

Example 2 with Realm

use of org.asynchttpclient.Realm in project async-http-client by AsyncHttpClient.

the class Interceptors method exitAfterIntercept.

public //
boolean exitAfterIntercept(//
Channel channel, //
NettyResponseFuture<?> future, //
AsyncHandler<?> handler, //
HttpResponse response, //
HttpResponseStatus status, HttpResponseHeaders responseHeaders) throws Exception {
    HttpRequest httpRequest = future.getNettyRequest().getHttpRequest();
    ProxyServer proxyServer = future.getProxyServer();
    int statusCode = response.status().code();
    Request request = future.getCurrentRequest();
    Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm();
    if (hasResponseFilters && responseFiltersInterceptor.exitAfterProcessingFilters(channel, future, handler, status, responseHeaders)) {
        return true;
    }
    if (statusCode == UNAUTHORIZED_401) {
        return unauthorized401Interceptor.exitAfterHandling401(channel, future, response, request, statusCode, realm, proxyServer, httpRequest);
    } else if (statusCode == PROXY_AUTHENTICATION_REQUIRED_407) {
        return proxyUnauthorized407Interceptor.exitAfterHandling407(channel, future, response, request, statusCode, proxyServer, httpRequest);
    } else if (statusCode == CONTINUE_100) {
        return continue100Interceptor.exitAfterHandling100(channel, future, statusCode);
    } else if (Redirect30xInterceptor.REDIRECT_STATUSES.contains(statusCode)) {
        return redirect30xInterceptor.exitAfterHandlingRedirect(channel, future, response, request, statusCode, realm);
    } else if (httpRequest.method() == HttpMethod.CONNECT && statusCode == OK_200) {
        return connectSuccessInterceptor.exitAfterHandlingConnect(channel, future, request, proxyServer, statusCode, httpRequest);
    }
    return false;
}
Also used : HttpRequest(io.netty.handler.codec.http.HttpRequest) HttpRequest(io.netty.handler.codec.http.HttpRequest) Request(org.asynchttpclient.Request) Realm(org.asynchttpclient.Realm) ProxyServer(org.asynchttpclient.proxy.ProxyServer)

Example 3 with Realm

use of org.asynchttpclient.Realm in project async-http-client by AsyncHttpClient.

the class ProxyUnauthorized407Interceptor method exitAfterHandling407.

public //
boolean exitAfterHandling407(//
Channel channel, //
NettyResponseFuture<?> future, //
HttpResponse response, //
Request request, //
int statusCode, //
ProxyServer proxyServer, HttpRequest httpRequest) {
    if (future.isAndSetInProxyAuth(true)) {
        LOGGER.info("Can't handle 407 as auth was already performed");
        return false;
    }
    Realm proxyRealm = future.getProxyRealm();
    if (proxyRealm == null) {
        LOGGER.debug("Can't handle 407 as there's no proxyRealm");
        return false;
    }
    List<String> proxyAuthHeaders = response.headers().getAll(PROXY_AUTHENTICATE);
    if (proxyAuthHeaders.isEmpty()) {
        LOGGER.info("Can't handle 407 as response doesn't contain Proxy-Authenticate headers");
        return false;
    }
    // FIXME what's this???
    future.setChannelState(ChannelState.NEW);
    HttpHeaders requestHeaders = new DefaultHttpHeaders(false).add(request.getHeaders());
    switch(proxyRealm.getScheme()) {
        case BASIC:
            if (getHeaderWithPrefix(proxyAuthHeaders, "Basic") == null) {
                LOGGER.info("Can't handle 407 with Basic realm as Proxy-Authenticate headers don't match");
                return false;
            }
            if (proxyRealm.isUsePreemptiveAuth()) {
                // FIXME do we need this, as future.getAndSetAuth
                // was tested above?
                // auth was already performed, most likely auth
                // failed
                LOGGER.info("Can't handle 407 with Basic realm as auth was preemptive and already performed");
                return false;
            }
            // FIXME do we want to update the realm, or directly
            // set the header?
            Realm newBasicRealm = //
            realm(proxyRealm).setUsePreemptiveAuth(//
            true).build();
            future.setProxyRealm(newBasicRealm);
            break;
        case DIGEST:
            String digestHeader = getHeaderWithPrefix(proxyAuthHeaders, "Digest");
            if (digestHeader == null) {
                LOGGER.info("Can't handle 407 with Digest realm as Proxy-Authenticate headers don't match");
                return false;
            }
            Realm newDigestRealm = //
            realm(proxyRealm).setUri(//
            request.getUri()).setMethodName(//
            request.getMethod()).setUsePreemptiveAuth(//
            true).parseProxyAuthenticateHeader(//
            digestHeader).build();
            future.setProxyRealm(newDigestRealm);
            break;
        case NTLM:
            String ntlmHeader = getHeaderWithPrefix(proxyAuthHeaders, "NTLM");
            if (ntlmHeader == null) {
                LOGGER.info("Can't handle 407 with NTLM realm as Proxy-Authenticate headers don't match");
                return false;
            }
            ntlmProxyChallenge(ntlmHeader, request, requestHeaders, proxyRealm, future);
            Realm newNtlmRealm = //
            realm(proxyRealm).setUsePreemptiveAuth(//
            true).build();
            future.setProxyRealm(newNtlmRealm);
            break;
        case KERBEROS:
        case SPNEGO:
            if (getHeaderWithPrefix(proxyAuthHeaders, NEGOTIATE) == null) {
                LOGGER.info("Can't handle 407 with Kerberos or Spnego realm as Proxy-Authenticate headers don't match");
                return false;
            }
            try {
                kerberosProxyChallenge(channel, proxyAuthHeaders, request, proxyServer, proxyRealm, requestHeaders, future);
            } catch (SpnegoEngineException e) {
                // FIXME
                String ntlmHeader2 = getHeaderWithPrefix(proxyAuthHeaders, "NTLM");
                if (ntlmHeader2 != null) {
                    LOGGER.warn("Kerberos/Spnego proxy auth failed, proceeding with NTLM");
                    ntlmProxyChallenge(ntlmHeader2, request, requestHeaders, proxyRealm, future);
                    Realm newNtlmRealm2 = //
                    realm(proxyRealm).setScheme(//
                    AuthScheme.NTLM).setUsePreemptiveAuth(//
                    true).build();
                    future.setProxyRealm(newNtlmRealm2);
                } else {
                    requestSender.abort(channel, future, e);
                    return false;
                }
            }
            break;
        default:
            throw new IllegalStateException("Invalid Authentication scheme " + proxyRealm.getScheme());
    }
    RequestBuilder nextRequestBuilder = new RequestBuilder(future.getCurrentRequest()).setHeaders(requestHeaders);
    if (future.getCurrentRequest().getUri().isSecured()) {
        nextRequestBuilder.setMethod(CONNECT);
    }
    final Request nextRequest = nextRequestBuilder.build();
    LOGGER.debug("Sending proxy authentication to {}", request.getUri());
    if (//
    future.isKeepAlive() && //
    !HttpUtil.isTransferEncodingChunked(httpRequest) && !HttpUtil.isTransferEncodingChunked(response)) {
        future.setConnectAllowed(true);
        future.setReuseChannel(true);
        requestSender.drainChannelAndExecuteNextRequest(channel, future, nextRequest);
    } else {
        channelManager.closeChannel(channel);
        requestSender.sendNextRequest(nextRequest, future);
    }
    return true;
}
Also used : HttpHeaders(io.netty.handler.codec.http.HttpHeaders) DefaultHttpHeaders(io.netty.handler.codec.http.DefaultHttpHeaders) RequestBuilder(org.asynchttpclient.RequestBuilder) DefaultHttpHeaders(io.netty.handler.codec.http.DefaultHttpHeaders) SpnegoEngineException(org.asynchttpclient.spnego.SpnegoEngineException) Request(org.asynchttpclient.Request) HttpRequest(io.netty.handler.codec.http.HttpRequest) Realm(org.asynchttpclient.Realm)

Example 4 with Realm

use of org.asynchttpclient.Realm in project async-http-client by AsyncHttpClient.

the class Unauthorized401Interceptor method exitAfterHandling401.

public //
boolean exitAfterHandling401(//
final Channel channel, //
final NettyResponseFuture<?> future, //
HttpResponse response, //
final Request request, //
int statusCode, //
Realm realm, //
ProxyServer proxyServer, HttpRequest httpRequest) {
    if (realm == null) {
        LOGGER.debug("Can't handle 401 as there's no realm");
        return false;
    }
    if (future.isAndSetInAuth(true)) {
        LOGGER.info("Can't handle 401 as auth was already performed");
        return false;
    }
    List<String> wwwAuthHeaders = response.headers().getAll(WWW_AUTHENTICATE);
    if (wwwAuthHeaders.isEmpty()) {
        LOGGER.info("Can't handle 401 as response doesn't contain WWW-Authenticate headers");
        return false;
    }
    // FIXME what's this???
    future.setChannelState(ChannelState.NEW);
    HttpHeaders requestHeaders = new DefaultHttpHeaders(false).add(request.getHeaders());
    switch(realm.getScheme()) {
        case BASIC:
            if (getHeaderWithPrefix(wwwAuthHeaders, "Basic") == null) {
                LOGGER.info("Can't handle 401 with Basic realm as WWW-Authenticate headers don't match");
                return false;
            }
            if (realm.isUsePreemptiveAuth()) {
                // FIXME do we need this, as future.getAndSetAuth
                // was tested above?
                // auth was already performed, most likely auth
                // failed
                LOGGER.info("Can't handle 401 with Basic realm as auth was preemptive and already performed");
                return false;
            }
            // FIXME do we want to update the realm, or directly
            // set the header?
            Realm newBasicRealm = //
            realm(realm).setUsePreemptiveAuth(//
            true).build();
            future.setRealm(newBasicRealm);
            break;
        case DIGEST:
            String digestHeader = getHeaderWithPrefix(wwwAuthHeaders, "Digest");
            if (digestHeader == null) {
                LOGGER.info("Can't handle 401 with Digest realm as WWW-Authenticate headers don't match");
                return false;
            }
            Realm newDigestRealm = //
            realm(realm).setUri(//
            request.getUri()).setMethodName(//
            request.getMethod()).setUsePreemptiveAuth(//
            true).parseWWWAuthenticateHeader(//
            digestHeader).build();
            future.setRealm(newDigestRealm);
            break;
        case NTLM:
            String ntlmHeader = getHeaderWithPrefix(wwwAuthHeaders, "NTLM");
            if (ntlmHeader == null) {
                LOGGER.info("Can't handle 401 with NTLM realm as WWW-Authenticate headers don't match");
                return false;
            }
            ntlmChallenge(ntlmHeader, request, requestHeaders, realm, future);
            Realm newNtlmRealm = //
            realm(realm).setUsePreemptiveAuth(//
            true).build();
            future.setRealm(newNtlmRealm);
            break;
        case KERBEROS:
        case SPNEGO:
            if (getHeaderWithPrefix(wwwAuthHeaders, NEGOTIATE) == null) {
                LOGGER.info("Can't handle 401 with Kerberos or Spnego realm as WWW-Authenticate headers don't match");
                return false;
            }
            try {
                kerberosChallenge(channel, wwwAuthHeaders, request, requestHeaders, realm, future);
            } catch (SpnegoEngineException e) {
                // FIXME
                String ntlmHeader2 = getHeaderWithPrefix(wwwAuthHeaders, "NTLM");
                if (ntlmHeader2 != null) {
                    LOGGER.warn("Kerberos/Spnego auth failed, proceeding with NTLM");
                    ntlmChallenge(ntlmHeader2, request, requestHeaders, realm, future);
                    Realm newNtlmRealm2 = //
                    realm(realm).setScheme(//
                    AuthScheme.NTLM).setUsePreemptiveAuth(//
                    true).build();
                    future.setRealm(newNtlmRealm2);
                } else {
                    requestSender.abort(channel, future, e);
                    return false;
                }
            }
            break;
        default:
            throw new IllegalStateException("Invalid Authentication scheme " + realm.getScheme());
    }
    final Request nextRequest = new RequestBuilder(future.getCurrentRequest()).setHeaders(requestHeaders).build();
    LOGGER.debug("Sending authentication to {}", request.getUri());
    if (//
    future.isKeepAlive() && //
    !HttpUtil.isTransferEncodingChunked(httpRequest) && !HttpUtil.isTransferEncodingChunked(response)) {
        future.setReuseChannel(true);
        requestSender.drainChannelAndExecuteNextRequest(channel, future, nextRequest);
    } else {
        channelManager.closeChannel(channel);
        requestSender.sendNextRequest(nextRequest, future);
    }
    return true;
}
Also used : HttpHeaders(io.netty.handler.codec.http.HttpHeaders) DefaultHttpHeaders(io.netty.handler.codec.http.DefaultHttpHeaders) RequestBuilder(org.asynchttpclient.RequestBuilder) DefaultHttpHeaders(io.netty.handler.codec.http.DefaultHttpHeaders) SpnegoEngineException(org.asynchttpclient.spnego.SpnegoEngineException) Request(org.asynchttpclient.Request) HttpRequest(io.netty.handler.codec.http.HttpRequest) Realm(org.asynchttpclient.Realm)

Example 5 with Realm

use of org.asynchttpclient.Realm in project camel by apache.

the class AhcComponent method createEndpoint.

@Override
protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
    String addressUri = createAddressUri(uri, remaining);
    // Do not set the HTTP URI because we still have all of the Camel internal
    // parameters in the URI at this point.
    AhcEndpoint endpoint = createAhcEndpoint(uri, this, null);
    setEndpointHeaderFilterStrategy(endpoint);
    endpoint.setClient(getClient());
    endpoint.setClientConfig(getClientConfig());
    endpoint.setBinding(getBinding());
    endpoint.setSslContextParameters(getSslContextParameters());
    setProperties(endpoint, parameters);
    if (IntrospectionSupport.hasProperties(parameters, CLIENT_CONFIG_PREFIX)) {
        DefaultAsyncHttpClientConfig.Builder builder = endpoint.getClientConfig() == null ? new DefaultAsyncHttpClientConfig.Builder() : AhcComponent.cloneConfig(endpoint.getClientConfig());
        if (endpoint.getClient() != null) {
            LOG.warn("The user explicitly set an AsyncHttpClient instance on the component or " + "endpoint, but this endpoint URI contains client configuration parameters.  " + "Are you sure that this is what was intended?  The AsyncHttpClient will be used" + " and the URI parameters will be ignored.");
        } else if (endpoint.getClientConfig() != null) {
            LOG.warn("The user explicitly set an AsyncHttpClientConfig instance on the component or " + "endpoint, but this endpoint URI contains client configuration parameters.  " + "Are you sure that this is what was intended?  The URI parameters will be applied" + " to a clone of the supplied AsyncHttpClientConfig in order to prevent unintended modification" + " of the explicitly configured AsyncHttpClientConfig.  That is, the URI parameters override the" + " settings on the explicitly configured AsyncHttpClientConfig for this endpoint.");
        }
        // special for realm builder
        Builder realmBuilder = null;
        if (IntrospectionSupport.hasProperties(parameters, CLIENT_REALM_CONFIG_PREFIX)) {
            // set and validate additional parameters on client config
            Map<String, Object> realmParams = IntrospectionSupport.extractProperties(parameters, CLIENT_REALM_CONFIG_PREFIX);
            // copy the parameters for the endpoint to have
            endpoint.setClientConfigRealmOptions(new LinkedHashMap<>(realmParams));
            Object principal = realmParams.remove("principal");
            Object password = realmParams.remove("password");
            if (ObjectHelper.isEmpty(principal)) {
                throw new IllegalArgumentException(CLIENT_REALM_CONFIG_PREFIX + ".principal must be configured");
            }
            if (password == null) {
                password = "";
            }
            realmBuilder = new Realm.Builder(principal.toString(), password.toString());
            setProperties(realmBuilder, realmParams);
            validateParameters(uri, realmParams, null);
        }
        // set and validate additional parameters on client config
        Map<String, Object> clientParams = IntrospectionSupport.extractProperties(parameters, CLIENT_CONFIG_PREFIX);
        // copy the parameters for the endpoint to have
        endpoint.setClientConfigOptions(new LinkedHashMap<>(clientParams));
        setProperties(builder, clientParams);
        validateParameters(uri, clientParams, null);
        if (realmBuilder != null) {
            builder.setRealm(realmBuilder.build());
        }
        endpoint.setClientConfig(builder.build());
    }
    // restructure uri to be based on the parameters left as we dont want to include the Camel internal options
    addressUri = UnsafeUriCharactersEncoder.encodeHttpURI(addressUri);
    URI httpUri = URISupport.createRemainingURI(new URI(addressUri), parameters);
    endpoint.setHttpUri(httpUri);
    return endpoint;
}
Also used : Builder(org.asynchttpclient.Realm.Builder) DefaultAsyncHttpClientConfig(org.asynchttpclient.DefaultAsyncHttpClientConfig) Builder(org.asynchttpclient.Realm.Builder) Realm(org.asynchttpclient.Realm) URI(java.net.URI)

Aggregations

Realm (org.asynchttpclient.Realm)9 Request (org.asynchttpclient.Request)6 RequestBuilder (org.asynchttpclient.RequestBuilder)4 SpnegoEngineException (org.asynchttpclient.spnego.SpnegoEngineException)4 DefaultHttpHeaders (io.netty.handler.codec.http.DefaultHttpHeaders)3 HttpHeaders (io.netty.handler.codec.http.HttpHeaders)3 HttpRequest (io.netty.handler.codec.http.HttpRequest)3 List (java.util.List)2 ProxyServer (org.asynchttpclient.proxy.ProxyServer)2 Bootstrap (io.netty.bootstrap.Bootstrap)1 EXPECT (io.netty.handler.codec.http.HttpHeaderNames.EXPECT)1 java.net (java.net)1 InetSocketAddress (java.net.InetSocketAddress)1 URI (java.net.URI)1 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 Properties (java.util.Properties)1 AsyncHttpClientConfig (org.asynchttpclient.AsyncHttpClientConfig)1 DefaultAsyncHttpClientConfig (org.asynchttpclient.DefaultAsyncHttpClientConfig)1 Dsl.basicAuthRealm (org.asynchttpclient.Dsl.basicAuthRealm)1