Apache HttpClient Digest authentication

前端 未结 4 1772
生来不讨喜
生来不讨喜 2020-11-28 13:28

Basically what I need to do is to perform digest authentication. First thing I tried is the official example available here. But when I try to execute it(with some small ch

相关标签:
4条回答
  • 2020-11-28 14:10

    This code snippet worked for me. You have to provide the realm which you can get by looking at the 401 response header you get from the host.

    val credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(AuthScope.ANY,
      new UsernamePasswordCredentials(user, password));
    val authCache = new BasicAuthCache();
    val digestScheme = new DigestScheme();
    
    digestScheme.overrideParamter("realm", "**Name of the Realm**");
    // Nonce value
    digestScheme.overrideParamter("nonce", "whatever");
    
    authCache.put(targetHost, digestScheme);
    
    context.setCredentialsProvider(credsProvider);
    context.setAuthCache(authCache);
    
    val httpget = new HttpGet(url);
    
    val response = httpClient.execute(targetHost, httpget, context);
    
    0 讨论(0)
  • 2020-11-28 14:15
    private static byte[] downloadFileWithDigitAuth(String url, String username, String password) {
        byte[] bytes = null;
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpGet httpGet = new HttpGet(url);
        HttpContext httpContext = new BasicHttpContext();
        CloseableHttpResponse httpResponse = null;
        try {
            httpResponse = httpClient.execute(httpGet, httpContext);
    
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
                Header authHeader = httpResponse.getFirstHeader(AUTH.WWW_AUTH);
                DigestScheme digestScheme = new DigestScheme();
    
                /*
                override values if need
                No need override values such as nonce, opaque, they are generated by server side
                */
                digestScheme.overrideParamter("realm", "User Login Required !!");
                digestScheme.processChallenge(authHeader);
    
                UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
                httpGet.addHeader(digestScheme.authenticate(creds, httpGet, httpContext));
    
                httpResponse.close();
                httpResponse = httpClient.execute(httpGet);
            }
            bytes = IOUtils.toByteArray(httpResponse.getEntity().getContent());
        } catch (IOException | MalformedChallengeException | AuthenticationException e) {
            e.printStackTrace();
        }
        finally {
            if (httpResponse != null) {
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return bytes;
    }
    

    Gradle :

    compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.12'
    compile group: 'commons-io', name: 'commons-io', version: '2.6'
    
    0 讨论(0)
  • 2020-11-28 14:20

    You guys make it so complicated. If you read the documentation of apache httpclient, it would be super easy.

    protected static void downloadDigest(URL url, FileOutputStream fos)
        throws IOException {
        HttpHost targetHost = new HttpHost(url.getHost(), url.getPort(), url.getProtocol());
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpClientContext context = HttpClientContext.create();
    
        String credential = url.getUserInfo();
        if (credential != null) {
            String user = credential.split(":")[0];
            String password = credential.split(":")[1];
    
            CredentialsProvider credsProvider = new BasicCredentialsProvider();
            credsProvider.setCredentials(AuthScope.ANY,
                new UsernamePasswordCredentials(user, password));
            AuthCache authCache = new BasicAuthCache();
            DigestScheme digestScheme = new DigestScheme();
            authCache.put(targetHost, digestScheme);
    
            context.setCredentialsProvider(credsProvider);
            context.setAuthCache(authCache);
        }
    
        HttpGet httpget = new HttpGet(url.getPath());
    
        CloseableHttpResponse response = httpClient.execute(targetHost, httpget, context);
    
        try {
            ReadableByteChannel rbc = Channels.newChannel(response.getEntity().getContent());
            fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
        } finally {
            response.close();
        }
    }
    
    0 讨论(0)
  • 2020-11-28 14:22

    I managed to do a Digest login using digestScheme after verifying the code.

    digestAuth.processChallenge(null);
    

    Forces the previous input parameters to be interpreted. The null parameter is a header, based on the header sent, if any.

    Now qop/nc is used and digestScheme works as required. Running it on android

    digestAuth.overrideParamter("algorithm", "MD5");
    digestAuth.overrideParamter("realm", serverRealm);
    digestAuth.overrideParamter("nonce", Long.toString(new Random().nextLong(), 36));
    digestAuth.overrideParamter("qop", "auth");//   not effective 
    digestAuth.overrideParamter("nc",""+sequence);//nt effective 
    digestAuth.overrideParamter("cnonce", DigestScheme.createCnonce());
    digestAuth.overrideParamter("opaque","ba897c2f0f3de9c6f52d");
    String err;
    try
    {
        digestAuth.processChallenge(null);
        //force  qop in use  chalange  on return header ????!!!!
    }
    catch (Exception e)
    { 
        err=e.getLocalizedMessage();
    }
    
    0 讨论(0)
提交回复
热议问题