類別 Win32::SSPI::NegotiateAuth

處理「協商」類型驗證。專門用於透過 HTTP 驗證代理伺服器

常數

B64_TOKEN_PREFIX

NTLM 令牌總是從此標頭開始。 編碼 本身會加入「==」和換行符號,因此請移除它們

REQUEST_FLAGS

SSPI 函式的預設要求旗標

屬性

context[RW]
contextAttributes[RW]
credentials[RW]
domain[RW]
user[RW]

公開類別方法

new(user = nil, domain = nil) 按一下以切換來源

建立新的執行個體,準備以指定網域中的指定使用者身分進行驗證。如果未提供任何參數,則預設為由 ENVENV 定義的目前使用者和網域。

# File ext/win32/lib/win32/sspi.rb, line 245
def initialize(user = nil, domain = nil)
  if user.nil? && domain.nil? && ENV["USERNAME"].nil? && ENV["USERDOMAIN"].nil?
    raise "A username or domain must be supplied since they cannot be retrieved from the environment"
  end

  @user = user || ENV["USERNAME"]
  @domain = domain || ENV["USERDOMAIN"]
end
proxy_auth_get(http, path, user = nil, domain = nil) 按一下以切換來源

針對連線和要求路徑,以目前使用者身分執行驗證,並傳回 GET 要求的回應。連線應為 Net::HTTP 物件,且應使用 Net::HTTP.Proxy 方法建構,但任何回應「get」的項目都可使用。如果提供使用者和網域,則會以指定使用者身分進行驗證。傳回從 get 方法接收到的回應(通常為 Net::HTTPResponse

# File ext/win32/lib/win32/sspi.rb, line 230
def NegotiateAuth.proxy_auth_get(http, path, user = nil, domain = nil)
  raise "http must respond to :get" unless http.respond_to?(:get)
  nego_auth = self.new user, domain

  resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
  if resp["Proxy-Authenticate"]
    resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(resp["Proxy-Authenticate"].split(" ").last.strip) }
  end

  resp
end

公開執行個體方法

complete_authentication(token) 按一下以切換來源

取得令牌並取得協商驗證鏈中的下一個令牌。令牌可以 Base64 編碼或不編碼。令牌可以包含「協商」標頭,且會將其移除。不會指出傳回的是 SEC_I_CONTINUE 還是 SEC_E_OK。傳回的令牌是 Base64 編碼,且已移除所有換行符號。

# File ext/win32/lib/win32/sspi.rb, line 278
def complete_authentication(token)
  raise "This object is no longer usable because its resources have been freed." if @cleaned_up

  # Nil token OK, just set it to empty string
  token = "" if token.nil?

  if token.include? "Negotiate"
    # If the Negotiate prefix is passed in, assume we are seeing "Negotiate <token>" and get the token.
    token = token.split(" ").last
  end

  if token.include? B64_TOKEN_PREFIX
    # indicates base64 encoded token
    token = token.strip.unpack("m")[0]
  end

  outputBuffer = SecurityBuffer.new
  result = SSPIResult.new(API::InitializeSecurityContext.call(@credentials.to_p, @context.to_p, nil,
    REQUEST_FLAGS, 0, SECURITY_NETWORK_DREP, SecurityBuffer.new(token).to_p, 0,
    @context.to_p,
    outputBuffer.to_p, @contextAttributes, TimeStamp.new.to_p))

  if result.ok? then
    return encode_token(outputBuffer.token)
  else
    raise "Error: #{result.to_s}"
  end
ensure
  # need to make sure we don't clean up if we've already cleaned up.
  clean_up unless @cleaned_up
end
get_initial_token() 按一下以切換來源

取得初始協商令牌。以適合用於 HTTP 的 Base64 編碼字串傳回。不過,可以輕鬆解碼。

# File ext/win32/lib/win32/sspi.rb, line 256
def get_initial_token
  raise "This object is no longer usable because its resources have been freed." if @cleaned_up
  get_credentials

  outputBuffer = SecurityBuffer.new
  @context = CtxtHandle.new
  @contextAttributes = "\0" * 4

  result = SSPIResult.new(API::InitializeSecurityContextA.call(@credentials.to_p, nil, nil,
    REQUEST_FLAGS,0, SECURITY_NETWORK_DREP, nil, 0, @context.to_p, outputBuffer.to_p, @contextAttributes, TimeStamp.new.to_p))

  if result.ok? then
    return encode_token(outputBuffer.token)
  else
    raise "Error: #{result.to_s}"
  end
end

私人實例方法

clean_up() 按一下以切換來源
# File ext/win32/lib/win32/sspi.rb, line 312
def clean_up
  # free structures allocated
  @cleaned_up = true
  API::FreeCredentialsHandle.call(@credentials.to_p)
  API::DeleteSecurityContext.call(@context.to_p)
  @context = nil
  @credentials = nil
  @contextAttributes = nil
end
encode_token(t) 按一下以切換來源
# File ext/win32/lib/win32/sspi.rb, line 332
def encode_token(t)
  # encode64 will add newlines every 60 characters so we need to remove those.
  [t].pack("m").delete("\n")
end
get_credentials() 按一下以切換來源

根據使用者、網域或兩者取得認證。如果兩者皆為 nil,則會發生錯誤

# File ext/win32/lib/win32/sspi.rb, line 323
def get_credentials
  @credentials = CredHandle.new
  ts = TimeStamp.new
  @identity = Identity.new @user, @domain
  result = SSPIResult.new(API::AcquireCredentialsHandleA.call(nil, "Negotiate", SECPKG_CRED_OUTBOUND, nil, @identity.to_p,
    nil, nil, @credentials.to_p, ts.to_p))
  raise "Error acquire credentials: #{result}" unless result.ok?
end