使用 IIS HTTP PlatformHandler 并使用 Windows 身份验证时,如何在 Python 中获取经过身份验证的用户名?

问题描述 投票:0回答:2

HttpPlatformHandler 通过启用 web.config 中的 forwardWindowsAuthToken 设置来支持转发身份验证令牌。 当需要使用 Windows 集成身份验证时,这听起来像是一个有用的功能。 文档对此非常模糊,没有解释如何使用此令牌来获取经过身份验证的用户名。

如果此设置设置为 true,令牌将被转发到 子进程以 %HTTP_PLATFORM_PORT% 作为标头侦听 每个请求的“X-IIS-WindowsAuthToken”。这是它的责任 处理每个请求对此令牌调用 CloseHandle。默认值 价值是假的。

在我的用例中,我需要将 Windows 集成身份验证与 Python 结合使用,因此使用 IIS 前端进行设置并使用 HTTP 平台处理程序将请求转发到 Python。

问题是,如何从 Python 中提供的令牌中获取用户名? “X-IIS-WindowsAuthToken”标头中的令牌看起来像 22b 一样的 3 字符十六进制。

python iis windows-authentication pywin32 httpplatformhandler
2个回答
2
投票

好的,所以我对此进行了一些研究,最后回顾了Microsoft.AspNetCore.Server.IISIntegrateion.AuthenticationHandler 是如何做到的。

然后在想出一种方法之后,我想发布这个答案,这样 1) 我可以稍后找到它,2) 至少它在 SO 上以防万一其他人想知道。

好的,所以十六进制值是句柄,我们可以使用句柄调用模拟用户然后获取用户名,完成。

您只需要 pywin32 包:

pip install pywin32

Python 中的完整示例:

import win32api
import win32security
if 'x-iis-windowsauthtoken' in request.headers.keys():
    handle_str = request.headers['x-iis-windowsauthtoken']
    handle = int(handle_str, 16) # need to convert from Hex / base 16
    win32security.ImpersonateLoggedOnUser(handle)
    user = win32api.GetUserName()
    win32security.RevertToSelf() # undo impersonation
    win32api.CloseHandle(handle) # don't leak resources, need to close the handle!
    print(f"user name: {user}")
    
    

0
投票

这篇文章对我很有用。有一件事我真的不知道冒充来获取用户信息是否是正确的方法。不过,我不是 Windows 专家。

所以我尝试了使用 GetTokenInformation 和 LookupAccountSid 的另一条路径。这次用的是我比较熟悉的ruby(ruby on rails)

我是第一次使用fiddle,但是我想说如果你对C稍有了解,fiddle并没有那么难。

我希望这篇文章能帮助在 Windows 平台上使用 ruby 的人。

require "fiddle/import"
require 'fiddle/types'

module WIN32Security
  extend Fiddle::Importer
  dlload 'advapi32.dll'
  include Fiddle::Win32Types

  extern 'BOOL GetTokenInformation(HANDLE, UINT, PVOID, DWORD, PDWORD)'
  extern 'BOOL LookupAccountSidW(LPSTR, PVOID, LPSTR, PDWORD, LPSTR, PDWORD, PVOID)'

  # c.f. https://learn.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-token_information_class
  TokenUser = 1
end

module WIN32
  extend Fiddle::Importer
  dlload 'kernel32.dll'
  include Fiddle::Win32Types
  extern 'BOOL CloseHandle(HANDLE)'
end

module SelfServicesHelper
  def authorize_by_authtoken
    if request.headers.key? "HTTP_X_IIS_WINDOWSAUTHTOKEN"
      handle = request.headers["HTTP_X_IIS_WINDOWSAUTHTOKEN"].hex

      buflen = 64
      tokenInfo, len = "\0" * buflen, [0].pack("L!")
      if WIN32Security::GetTokenInformation(handle, WIN32Security::TokenUser, tokenInfo, buflen, len) != 0
        namelen, dnamelen, use = *[32,32].map{|e| [e].pack("L!")}, [0].pack("I")
        namebuf, dnamebuf = [namelen, dnamelen].map{|e| "\0".encode("utf-16le") * e.unpack1("L!")}
        # ... PSID is at the top of tokenInfo
        if WIN32Security::LookupAccountSidW(nil, tokenInfo.unpack1("Q!"), namebuf, namelen, dnamebuf, dnamelen, use) != 0
          namelen, dnamelen = [namelen, dnamelen].map{|e| e.unpack1("L!")}
          WIN32::CloseHandle(handle)
          logger.debug {"namebuf: %s, dnamebuf: %s" % [namebuf[0, namelen].encode("utf-8"), dnamebuf[0, dnamelen].encode("utf-8")}
        else
          logger.error "LookupAccountSidW returned false, last error: %d" % Fiddle.win32_last_error
        end
      else
        logger.error "GetTokenInformation returned false, last error: %d" % Fiddle.win32_last_error
      end
    else
      logger.debug "no HTTP_X_IIS_WINDOWSAUTHTOKEN"
    end
  end
end
© www.soinside.com 2019 - 2024. All rights reserved.