使用Jersey Client进行摘要式身份验证

时间:2010-06-02 08:43:37

标签: java jersey http-authentication

我已经使用Jersey Server编写了一个 REST Web服务(完全是摇滚!)。 我现在正在使用Jersey Client开发它的客户端部分。

在服务器端,我选择了 DIGEST 身份验证,因为我个人认为 BASIC 身份验证是一种异端,应该在我们的头脑中标记为“已弃用”

不幸的是,我在客户端看不到任何Digest身份验证的支持。 对于 BASIC 身份验证,可以执行以下操作:

client.addFilter(
    new HTTPBasicAuthFilter(
        user, 
        password));

但我看不到“ HTTPDigestAuthFilter ”对应物。 我错过了什么吗?

感谢您的帮助,

圣拉斐尔

2 个答案:

答案 0 :(得分:23)

我刚刚实现了它。 我在Jersey问题跟踪器中创建了一个功能请求,并在那里发布了我的实现,作为附件: https://jersey.dev.java.net/issues/show_bug.cgi?id=542

它适用于与Tomcat服务器的DIGEST身份验证进行通信。 我还没有测试过其他网络服务器。

答案 1 :(得分:0)

这里我写了一些随机的uri。请填写您想要的URI

对于样本测试,您可以获取互联网上可用的谷歌服务的帮助。

    import javax.ws.rs.core.*;
    import org.apache.commons.codec.digest.*;
    import org.codehaus.jettison.json.*;
    import com.sun.jersey.api.*;


    public class DigestClient {

    //Dividing into two parts because we need to send the last part of uri in our second request to service.
    static String baseUri = "https://www.something.com";
    static String subUri = "/later-part";

    public static void main(String[] args) throws JSONException{

        ClientConfig cc = new DefaultClientConfig();
        Client client = Client.create(cc);

        WebResource webResource = client.resource(baseUri+subUri);
        ClientResponse response = webResource.get(ClientResponse.class);
        // Basically in Digest-Authentication mechanism, we hit the rest service two times. 
        // First time with No Authentication, which returns some values (qop, nonce, realm) which are used as inputs in second call to rest service.


        /*--------------- First call-----------------*/
        // We get 401, Unauthorized
        System.out.println(response.getStatus()+"   "+response.getStatusInfo());
        // Here is the complete header information
        System.out.println(response.getHeaders());
        // We need "WWW-Authenticate" part information for our second call to rest
        System.out.println("WWW-Authenticate: \t" + response.getHeaders().get("www-Authenticate"));


        String noAuthResp = response.getHeaders().get("www-Authenticate").toString();
        noAuthResp = noAuthResp.replace("Digest ", "");
        noAuthResp = noAuthResp.replace('[', '{');
        noAuthResp = noAuthResp.replace(']', '}');

        // Creating a JSONObject for easy information retrieval 
        JSONObject resp = new JSONObject(noAuthResp);


        /*--------------- Second call-----------------*/
        // Here client has to set the fields which was returned from the first call
        String user = "postman";          // username
        String password = "password";          // password
        String realm = resp.getString("realm");          // realm value from the first rest-call response
        String qop = resp.getString("qop");          //qop value from the first rest-call response
        String nonce = resp.getString("nonce");          // nonce value from the first rest-call response
        String opaque = resp.getString("opaque");          // Some times if we don't get this value, set it with ""
        String algorithm = "MD5";          // The algorithm set by the  client
        int nonceCount = 678;          // Some numerical input from the client
        String clientNonce = "afdjas0";          // Some random text from the client for encryption

        String method = "GET";          // HTTP method

        String ha1 = new DigestClient().formHA1(user, realm, password);
        String ha2 = new DigestClient().formHA2(method, subUri);
        String responseCode =  new DigestClient().generateResponse(ha1, nonce, nonceCount, clientNonce, qop, ha2);

        // Header to be sent to the service
        String value = "Digest username=\""+user+"\", realm=\""+realm+"\", nonce=\""+nonce+"\", uri=\""+subUri+"\", qop="+qop+", nc="+nonceCount+", cnonce=\""+clientNonce+"\", response=\""+responseCode+"\", opaque=\""+opaque+"\"";          

        // Hitting the service
        response = webResource.header("authorization", value).type(MediaType.TEXT_PLAIN).accept("*").get(ClientResponse.class);
        System.out.println("\nComplete Response:\n"+response+"\n");
        String output = response.getEntity(String.class);
        System.out.println("Response Text: "+output);
    }

    // For generating HA1 value
    public String formHA1(String userName,String realm,String password){
        String ha1 = DigestUtils.md5Hex(userName + ":" + realm + ":" + password);
        return ha1;
    }
    // For generating HA2 value
    public String formHA2(String method,String uri){
        String ha2=DigestUtils.md5Hex(method + ":" + uri);
        return ha2;
    }

    // For generating response at client side
    public String generateResponse(String ha1,String nonce,int nonceCount,String clientNonce,String qop,String ha2){
        String response=DigestUtils.md5Hex(ha1 + ":" + nonce + ":" + nonceCount + ":" +clientNonce +":" + qop + ":" +ha2);
        return response;

    }
    }