add auth_params
parent
67051da876
commit
c46539ea44
|
@ -0,0 +1,33 @@
|
||||||
|
require "./spec_helper"
|
||||||
|
|
||||||
|
describe "Mechanize HTTP Authentication test" do
|
||||||
|
it "auth_param" do
|
||||||
|
parser = Mechanize::HTTP::WWWAuthenticateParser.new
|
||||||
|
parser.scanner = StringScanner.new("realm=here")
|
||||||
|
parser.auth_param.should eq ["realm", "here"]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "auth_param no value" do
|
||||||
|
parser = Mechanize::HTTP::WWWAuthenticateParser.new
|
||||||
|
parser.scanner = StringScanner.new("realm=")
|
||||||
|
parser.auth_param.should eq nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "auth_param bad token" do
|
||||||
|
parser = Mechanize::HTTP::WWWAuthenticateParser.new
|
||||||
|
parser.scanner = StringScanner.new("realm")
|
||||||
|
parser.auth_param.should eq nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "auth_param bad value" do
|
||||||
|
parser = Mechanize::HTTP::WWWAuthenticateParser.new
|
||||||
|
parser.scanner = StringScanner.new("realm=\"this ")
|
||||||
|
parser.auth_param.should eq nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "auth_param with quote" do
|
||||||
|
parser = Mechanize::HTTP::WWWAuthenticateParser.new
|
||||||
|
parser.scanner = StringScanner.new("realm=\"this site\"")
|
||||||
|
parser.auth_param.should eq ["realm", "this site"]
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,7 @@
|
||||||
require "../cookie"
|
require "../cookie"
|
||||||
require "../history"
|
require "../history"
|
||||||
require "./auth_store"
|
require "./auth_store"
|
||||||
|
require "./www_authenticate_parser"
|
||||||
|
|
||||||
class Mechanize
|
class Mechanize
|
||||||
module HTTP
|
module HTTP
|
||||||
|
@ -169,7 +170,7 @@ class Mechanize
|
||||||
private def save_response_cookies(response, uri, page)
|
private def save_response_cookies(response, uri, page)
|
||||||
if page.body =~ /Set-Cookie/
|
if page.body =~ /Set-Cookie/
|
||||||
page.css("head meta[http-equiv=\"Set-Cookie\"]").each do |meta|
|
page.css("head meta[http-equiv=\"Set-Cookie\"]").each do |meta|
|
||||||
cookie = meta["content"].split(";")[0]
|
cookie = meta["content"].split(";") # [0]
|
||||||
key, value = cookie.split("=")
|
key, value = cookie.split("=")
|
||||||
cookie = ::HTTP::Cookie.new(name: key, value: value)
|
cookie = ::HTTP::Cookie.new(name: key, value: value)
|
||||||
save_cookies(uri, [cookie])
|
save_cookies(uri, [cookie])
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
class Mechanize
|
||||||
|
module HTTP
|
||||||
|
##
|
||||||
|
# A parsed WWW-Authenticate header
|
||||||
|
|
||||||
|
class AuthChallenge
|
||||||
|
property scheme : String?
|
||||||
|
property params : String?
|
||||||
|
|
||||||
|
def initialize(scheme = nil, params = nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
# def [] param
|
||||||
|
# params[param]
|
||||||
|
# end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Constructs an AuthRealm for this challenge
|
||||||
|
|
||||||
|
def realm(uri)
|
||||||
|
case scheme
|
||||||
|
when "Basic"
|
||||||
|
# raise ArgumentError, "provide uri for Basic authentication" unless uri
|
||||||
|
Mechanize::HTTP::AuthRealm.new scheme, uri + '/', self["realm"]
|
||||||
|
when "Digest"
|
||||||
|
Mechanize::HTTP::AuthRealm.new scheme, uri + '/', self["realm"]
|
||||||
|
else
|
||||||
|
# raise Mechanize::Error, "unknown HTTP authentication scheme #{scheme}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# The name of the realm for this challenge
|
||||||
|
|
||||||
|
def realm_name
|
||||||
|
params["realm"] if Hash === params # NTLM has a string for params
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# The raw authentication challenge
|
||||||
|
|
||||||
|
# alias to_s raw
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,166 @@
|
||||||
|
require "string_scanner"
|
||||||
|
require "./auth_challenge"
|
||||||
|
|
||||||
|
##
|
||||||
|
# Parses the WWW-Authenticate HTTP header into separate challenges.
|
||||||
|
|
||||||
|
class Mechanize
|
||||||
|
module HTTP
|
||||||
|
class WWWAuthenticateParser
|
||||||
|
property scanner : StringScanner
|
||||||
|
|
||||||
|
# Creates a new header parser for WWW-Authenticate headers
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@scanner = StringScanner.new("")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parsers the header. Returns an Array of challenges as strings
|
||||||
|
|
||||||
|
def parse(www_authenticate : String)
|
||||||
|
challenges = [Mechanize::HTTP::AuthChallenge]
|
||||||
|
scanner = StringScanner.new(www_authenticate)
|
||||||
|
|
||||||
|
loop do
|
||||||
|
break if scanner.eos?
|
||||||
|
start = scanner.pos
|
||||||
|
challenge = Mechanize::HTTP::AuthChallenge.new
|
||||||
|
|
||||||
|
scheme = auth_scheme
|
||||||
|
if scheme == "Negotiate"
|
||||||
|
scan_comma_spaces
|
||||||
|
end
|
||||||
|
|
||||||
|
break unless scheme
|
||||||
|
challenge.scheme = scheme
|
||||||
|
|
||||||
|
space = spaces
|
||||||
|
|
||||||
|
if scheme == "NTLM"
|
||||||
|
if space
|
||||||
|
challenge.params = scanner.scan(/.*/)
|
||||||
|
end
|
||||||
|
|
||||||
|
# challenge.raw = www_authenticate[start, @scanner.pos]
|
||||||
|
challenges << challenge
|
||||||
|
next
|
||||||
|
else
|
||||||
|
scheme.capitalize!
|
||||||
|
end
|
||||||
|
|
||||||
|
# next unless space
|
||||||
|
# params = {}
|
||||||
|
|
||||||
|
# while true do
|
||||||
|
# pos = @scanner.pos
|
||||||
|
# name, value = auth_param
|
||||||
|
|
||||||
|
# name.downcase! if name =~ /^realm$/i
|
||||||
|
|
||||||
|
# unless name then
|
||||||
|
# challenge.params = params
|
||||||
|
# challenges << challenge
|
||||||
|
|
||||||
|
# if @scanner.eos? then
|
||||||
|
# challenge.raw = www_authenticate[start, @scanner.pos]
|
||||||
|
# break
|
||||||
|
# end
|
||||||
|
|
||||||
|
# @scanner.pos = pos # rewind
|
||||||
|
# challenge.raw = www_authenticate[start, @scanner.pos].sub(/(,+)? *$/, '')
|
||||||
|
# challenge = nil # a token should be next, new challenge
|
||||||
|
# break
|
||||||
|
# else
|
||||||
|
# params[name] = value
|
||||||
|
# end
|
||||||
|
|
||||||
|
# spaces
|
||||||
|
|
||||||
|
# @scanner.scan(/(, *)+/)
|
||||||
|
# end
|
||||||
|
end
|
||||||
|
|
||||||
|
challenges
|
||||||
|
end
|
||||||
|
|
||||||
|
# scans a comma followed by spaces
|
||||||
|
# needed for Negotiation, NTLM
|
||||||
|
|
||||||
|
def scan_comma_spaces
|
||||||
|
scanner.scan(/, +/)
|
||||||
|
end
|
||||||
|
|
||||||
|
# token = 1*<any CHAR except CTLs or separators>
|
||||||
|
#
|
||||||
|
# Parses a token
|
||||||
|
|
||||||
|
def token
|
||||||
|
scanner.scan(/[^\000-\037\177()<>@,;:\\"\/\[\]?={} ]+/)
|
||||||
|
end
|
||||||
|
|
||||||
|
def auth_scheme
|
||||||
|
token
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# 1*SP
|
||||||
|
#
|
||||||
|
# Parses spaces
|
||||||
|
|
||||||
|
def spaces
|
||||||
|
scanner.scan(/ +/)
|
||||||
|
end
|
||||||
|
|
||||||
|
# auth-param = token "=" ( token | quoted-string )
|
||||||
|
#
|
||||||
|
# Parses an auth parameter
|
||||||
|
|
||||||
|
def auth_param : Array(String)?
|
||||||
|
return nil unless name = token
|
||||||
|
return nil unless scanner.scan(/ *= */)
|
||||||
|
|
||||||
|
value = if scanner.peek(1) == "\""
|
||||||
|
quoted_string
|
||||||
|
else
|
||||||
|
token
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil unless value
|
||||||
|
|
||||||
|
return [name, value]
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
|
||||||
|
# qdtext = <any TEXT except <">>
|
||||||
|
# quoted-pair = "\" CHAR
|
||||||
|
#
|
||||||
|
# For TEXT, the rules of RFC 2047 are ignored.
|
||||||
|
|
||||||
|
def quoted_string
|
||||||
|
return nil unless @scanner.scan(/"/)
|
||||||
|
|
||||||
|
text = String.new
|
||||||
|
|
||||||
|
loop do
|
||||||
|
chunk = scanner.scan(/[\r\n \t\x21\x23-\x7e\x{0080}-\x{00ff}]+/) # not " which is \x22
|
||||||
|
|
||||||
|
if chunk
|
||||||
|
text += chunk
|
||||||
|
|
||||||
|
text += (scanner.scan(/./) || "") if chunk.ends_with?("\\") && "\"" == scanner.peek(1)
|
||||||
|
else
|
||||||
|
if "\"" == scanner.peek(1)
|
||||||
|
scanner.scan(/./)
|
||||||
|
break
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
text
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue