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.