Digest authentication in Android using HttpURLConnection

前端 未结 5 701
终归单人心
终归单人心 2020-12-03 16:05

as the question allready says, I am trying to do digest authentication in android.
Until now i have used the DefaultHttpClient and it\'s authentication meth

5条回答
  •  情话喂你
    2020-12-03 16:32

    I finally replaced the deprecated DefaultHttpClient with my own implementation of the HttpUrlConnection and I implemented digest atuhentication myself, using this as a template.
    The finaly code looks something like this:

    // requestMethod: "GET", "POST", "PUT" etc.
    // Headers: A map with the HTTP-Headers for the request
    // Data: Body-Data for Post/Put
    int statusCode = this.requestImpl(requestMethod, headers, data);
    if (statusCode == HttpURLConnection.HTTP_UNAUTHORIZED && hasUserNameAndPassword) {
        String auth = getResponseHeaderField("WWW-Authenticate");
        // Server needs Digest authetication
        if(auth.startsWith("Digest")){
              // Parse the auth Header
              HashMap authFields = parseWWWAuthenticateHeader(auth);
              // Generate Auth-Value for request
              String requestAuth = generateDigestAuth(authFields);
              headers.put("Authorization", authStr);
              statusCode = this.requestImpl(requestMethod, headers, data);
        }
    }
    

    So basicly I make a request and if it returns 401, I look, if the server wants digest authentication and if I have username and password. If thats the case, I parse the auth header of the response, which contains all the necessary informations about the authentication.
    To parse the auth header I use some kind of StateMachine which is described here.
    After parsing the response auth header, I generate the request auth header using the informations from the response:

        String digestAuthStr = null;
    
        String uri = getURL().getPath();
        String nonce = authFields.get("nonce");
        String realm = authFields.get("realm");
        String qop = authFields.get("qop");
        String algorithm = authFields.get("algorithm");
        String cnonce = generateCNonce();
        String nc = "1";
        String ha1 = toMD5DigestString(concatWithSeparator(":", username, realm, password));
        String ha2 = toMD5DigestString(concatWithSeparator(":", requestMethod, uri));
        String response = null;
        if (!TextUtils.isEmpty(ha1) && !TextUtils.isEmpty(ha2))
            response = toMD5DigestString(concatWithSeparator(":", ha1, nonce, nc, cnonce, qop, ha2));
    
        if (response != null) {
            StringBuilder sb = new StringBuilder(128);
            sb.append("Digest ");
            sb.append("username").append("=\"").append(username).append("\", ");
            sb.append("realm").append("=\"").append(realm).append("\", ");
            sb.append("nonce").append("=\"").append(nonce).append("\", ");
            sb.append("uri").append("=\"").append(uri).append("\", ");
            sb.append("qop").append("=\"").append(qop).append("\", ");
            sb.append("nc").append("=\"").append(nc).append("\", ");
            sb.append("cnonce").append("=\"").append(cnonce).append("\"");
            sb.append("response").append("=\"").append(response).append("\"");
            sb.append("algorithm").append("=\"").append(algorithm).append("\"");
            digestAuthStr = sb.toString();
        }
    

    To generate the Client-Nonce I am using the following code:

    private static String generateCNonce() {
        String s = "";
        for (int i = 0; i < 8; i++)
            s += Integer.toHexString(new Random().nextInt(16));
        return s;
    }
    

    I hope this helps someone. If the code contains any errors, please let me know so I can fix it. But right now it seems to work.

提交回复
热议问题