HTTP Digest authentication

(Digest authentication是一个简单的认证机制最初是为HTTP协议开发的因而也常叫做HTTP摘要RFC2671中描述。其身份验证机制很简单,它采用杂凑式(hash)加密方法,以避免用明文传输用户的口令。

摘要认证就是要核实,参与通信的双方,都知道双方共享的一个秘密(即口令)。

 

当服务器想要查证用户的身份,它产生一个摘要盘问(digest challenge),并发送给用户。典型的摘要盘问如下:

 

Digest realm="iptel.org", qop="auth,auth-int",

nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="", algorithm=MD5

 

这里包括了一组参数,也要发送给用户。用户使用这些参数,来产生正确的摘要回答,并发送给服务器。摘要盘问中的各个参数,其意义如下:

 

realm(领域):领域参数是强制的,在所有的盘问中都必须有。它是目的是鉴别SIP消息中的机密。在SIP实际应用中,它通常设置为SIP代理服务器所负责的域名。

 

在要求用户输入用户名和口令时,SIP用户代理则会显示这个参数的内容给用户,以便用户使用正确的用户名和口令(这个服务器的)。

 

nonce(现时):这是由服务器规定的数据字符串,在服务器每次产生一个摘要盘问时,这个参数都是不一样的(与前面所产生的不会雷同)。现时通常是由一些数据通过md5杂凑运算构造的。

这样的数据通常包括时间标识和服务器的机密短语。这确保每个现时都有一个有限的生命期(也就是过了一些时间后会失效,并且以后再也不会使用),而且是独一无二的

(即任何其它的服务器都不能产生一个相同的现时)。

 

客户端使用这个现时来产生摘要响应(digest response),这样服务器也会在一个摘要响应中收到现时的内容。服务器先要检查了现时的有效性后,才会检查摘要响应的其它部分。

 

因而,现时在本质上是一种标识符,确保收到的摘要机密,是从某个特定的摘要盘问产生的。还限制了摘要盘问的生命期,防止未来的重播攻击。

opaque(不透明体):这是一个不透明的(不让外人知道其意义)数据字符串,在盘问中发送给用户。

在摘要响应中,用户会将这个数据字符串发送回给服务器。这使得服务器可以是无状态的。如果需要在盘问和响应之间维护一些状态,可以用这个参数传送状态给客户端,此后当摘要响应回来时,再读这个状态。

 

algorithm(算法):这是用来计算杂凑的算法。当前只支持MD5算法。

 

qop(保护的质量)。这个参数规定服务器支持哪种保护方案。客户端可以从列表中选择一个。值

 auth表示只进行身份查验, auth-int表示进行查验外,还有一些完整性保护。需要看更详细的描述,请参阅RFC2617。

 

在收到了摘要盘问后,如果没有预先配置,用户代理软件通常会提示用户输入用户名和口令,产生一个摘要响应,并将这个响应发送给服务器。例如,摘要响应可能如下:

 

Digest username="jan", realm="iptel.org",

nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", uri="sip:iptel.org",

qop=auth, nc=00000001, cnonce="0a4f113b",

response="6629fae49393a05397450978507c4ef1", opaque=""

 

摘要响应类似于摘要盘问。相同的参数则与摘要盘问有相同的意义。这里只描述新的参数:

uri(统一资源指示符):这个参数包含了客户端想要访问的URI。

qop:客户端选择的保护方式。

 

nc:现时计数器,这是一个16进制的数值,即客户端发送出请求的数量(包括当前这个请求),这些请求都使用了当前请求中这个现时值。例如,对一个给定的现时值,在响应的第一个请求中,客户端将发送nc=00000001。这个指示值的目的,是让服务器保持这个计数器的一个副本,以便检测重复的请求。如果这个相同的值看到了两次,则这个请求是重复的。

 

cnonce:这也是一个不透明的字符串值,由客户端提供,并且客户端和服务器都会使用,以避免用明文文本。这使得双方都可以查验对方的身份,并对消息的完整性提供一些保护。

 

response(响应):这是由用户代理软件计算出的一个字符串,以证明用户知道口令。

 

当服务器接收到摘要响应,也要重新计算响应中各参数的值,并利用客户端提供的参数值,和服务器上存储的口令,进行比对。如果计算结果与收到的客户响应值是相同的,则客户已证明它知道口令,

因而客户的身份验证通过。`

 

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
要在OkHttpClient中添加digest auth,你需要实现OkHttp的Authenticator接口,并将其设置到OkHttpClient中。具体的步骤如下: 1. 创建一个实现了Authenticator接口的类,例如DigestAuthenticator。 ```java public class DigestAuthenticator implements Authenticator { private final String username; private final String password; public DigestAuthenticator(String username, String password) { this.username = username; this.password = password; } @Override public Request authenticate(Route route, Response response) throws IOException { String challenge = response.header("WWW-Authenticate"); if (challenge == null || !challenge.startsWith("Digest ")) { // Challenge was not a digest authentication challenge. return null; } // Parse the challenge parameters. Map<String, String> params = parseChallengeParameters(challenge.substring("Digest ".length())); // Compute the response value. String uri = response.request().url().toString(); String realm = params.get("realm"); String nonce = params.get("nonce"); String qop = params.get("qop"); String nc = "00000001"; String cnonce = "0a4f113b"; String method = response.request().method(); String ha1 = md5(username + ":" + realm + ":" + password); String ha2 = md5(method + ":" + uri); String responseValue = md5(ha1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2); // Build the authentication header. String headerValue = "Digest " + "username=\"" + username + "\", " + "realm=\"" + realm + "\", " + "nonce=\"" + nonce + "\", " + "uri=\"" + uri + "\", " + "qop=" + qop + ", " + "nc=" + nc + ", " + "cnonce=\"" + cnonce + "\", " + "response=\"" + responseValue + "\", " + "opaque=\"" + params.get("opaque") + "\""; // Return the authenticated request. return response.request().newBuilder() .header("Authorization", headerValue) .build(); } private Map<String, String> parseChallengeParameters(String challenge) { // Parse the challenge parameters. Map<String, String> params = new HashMap<>(); for (String param : challenge.split(",\\s*")) { int equalsIndex = param.indexOf('='); if (equalsIndex != -1) { String key = param.substring(0, equalsIndex).trim(); String value = param.substring(equalsIndex + 1).trim(); if (value.startsWith("\"") && value.endsWith("\"")) { value = value.substring(1, value.length() - 1); } params.put(key, value); } } return params; } private static String md5(String s) { try { MessageDigest digest = MessageDigest.getInstance("MD5"); byte[] bytes = digest.digest(s.getBytes("UTF-8")); return ByteString.of(bytes).hex(); } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { throw new AssertionError(e); } } } ``` 上述代码中的md5方法是用来计算MD5值的,使用了OkHttp中的ByteString类。 2. 创建一个OkHttpClient对象,并将DigestAuthenticator设置为它的Authenticator。 ```java OkHttpClient client = new OkHttpClient.Builder() .authenticator(new DigestAuthenticator("username", "password")) .build(); ``` 在创建OkHttpClient对象时,使用Builder模式设置了Authenticator,将DigestAuthenticator对象作为参数传递给它。 3. 使用OkHttpClient对象来发送请求。 ```java Request request = new Request.Builder() .url("http://example.com") .build(); Response response = client.newCall(request).execute(); ``` 在发送请求时,使用了OkHttpClient对象来发送请求。如果服务器需要digest auth认证,OkHttpClient会自动使用设置的Authenticator进行认证。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值