Object
Authentication filter for handling DigestAuth negotiation. Used in WWWAuth.
Creates new DigestAuth filter.
# File lib/httpclient/auth.rb, line 268
268: def initialize
269: @auth = {}
270: @challenge = {}
271: @nonce_count = 0
272: @scheme = "Digest"
273: end
Challenge handler: remember URL and challenge token for response.
# File lib/httpclient/auth.rb, line 309
309: def challenge(uri, param_str)
310: @challenge[uri] = parse_challenge_param(param_str)
311: true
312: end
Response handler: returns credential. It sends cred only when a given uri is;
child page of challengeable(got *Authenticate before) uri and,
child page of defined credential
# File lib/httpclient/auth.rb, line 294
294: def get(req)
295: target_uri = req.header.request_uri
296: param = Util.hash_find_value(@challenge) { |uri, v|
297: Util.uri_part_of(target_uri, uri)
298: }
299: return nil unless param
300: user, passwd = Util.hash_find_value(@auth) { |uri, auth_data|
301: Util.uri_part_of(target_uri, uri)
302: }
303: return nil unless user
304: uri = req.header.request_uri
305: calc_cred(req.header.request_method, uri, user, passwd, param)
306: end
this method is implemented by sromano and posted to tools.assembla.com/breakout/wiki/DigestForSoap Thanks! supported algorithm: MD5 only for now
# File lib/httpclient/auth.rb, line 320
320: def calc_cred(method, uri, user, passwd, param)
321: a_1 = "#{user}:#{param['realm']}:#{passwd}"
322: a_2 = "#{method}:#{uri.path}"
323: nonce = param['nonce']
324: cnonce = generate_cnonce()
325: @nonce_count += 1
326: message_digest = []
327: message_digest << Digest::MD5.hexdigest(a_1)
328: message_digest << nonce
329: message_digest << ('%08x' % @nonce_count)
330: message_digest << cnonce
331: message_digest << param['qop']
332: message_digest << Digest::MD5.hexdigest(a_2)
333: header = []
334: header << "username=\"#{user}\""
335: header << "realm=\"#{param['realm']}\""
336: header << "nonce=\"#{nonce}\""
337: header << "uri=\"#{uri.path}\""
338: header << "cnonce=\"#{cnonce}\""
339: header << "nc=#{'%08x' % @nonce_count}"
340: header << "qop=\"#{param['qop']}\""
341: header << "response=\"#{Digest::MD5.hexdigest(message_digest.join(":"))}\""
342: header << "algorithm=\"MD5\""
343: header << "opaque=\"#{param['opaque']}\"" if param.key?('opaque')
344: header.join(", ")
345: end
cf. WEBrick::HTTPAuth::DigestAuth#generate_next_nonce(aTime)
# File lib/httpclient/auth.rb, line 348
348: def generate_cnonce
349: now = "%012d" % Time.now.to_i
350: pk = Digest::MD5.hexdigest([now, self.__id__, Process.pid, rand(65535)].join)[0, 32]
351: [now + ':' + pk].pack('m*').chop
352: end
# File lib/httpclient/auth.rb, line 354
354: def parse_challenge_param(param_str)
355: param = {}
356: param_str.scan(/\s*([^\,]+(?:\\.[^\,]*)*)/).each do |str|
357: key, value = str[0].scan(/\A([^=]+)=(.*)\z/)[0]
358: if /\A"(.*)"\z/ =~ value
359: value = $1.gsub(/\\(.)/, '\1')
360: end
361: param[key] = value
362: end
363: param
364: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.