Python中的NTLM认证
我正在尝试在IIS(Windows Server 2003)上实现NTLM认证,使用的是Windows 7和Python。局域网管理器认证级别设置为:仅发送NTLM响应。
客户端和服务器在同一个域中。
域控制器(活动目录)在另一台服务器上(同样运行Windows Server 2003)。
我收到401.1 - 未授权:由于凭据无效,访问被拒绝。
你能帮我找出这段代码有什么问题吗?或者给我一些其他可能的解决方案(使用NTLM或Kerberos)?
import sys, httplib, base64, string
import urllib2
import win32api
import sspi
import pywintypes
import socket
class WindoewNtlmMessageGenerator:
def __init__(self,user=None):
import win32api,sspi
if not user:
user = win32api.GetUserName()
self.sspi_client = sspi.ClientAuth("NTLM",user)
def create_auth_req(self):
import pywintypes
output_buffer = None
error_msg = None
try:
error_msg, output_buffer = self.sspi_client.authorize(None)
except pywintypes.error:
return None
auth_req = output_buffer[0].Buffer
auth_req = base64.encodestring(auth_req)
auth_req = string.replace(auth_req,'\012','')
return auth_req
def create_challenge_response(self,challenge):
import pywintypes
output_buffer = None
input_buffer = challenge
error_msg = None
try:
error_msg, output_buffer = self.sspi_client.authorize(input_buffer)
except pywintypes.error:
return None
response_msg = output_buffer[0].Buffer
response_msg = base64.encodestring(response_msg)
response_msg = string.replace(response_msg,'\012','')
return response_msg
fname='request.xml'
request = file(fname).read()
ip_host = '10.0.3.112'
ntlm_gen = WindoewNtlmMessageGenerator()
auth_req_msg = ntlm_gen.create_auth_req()
auth_req_msg_dec = base64.decodestring(auth_req_msg)
auth_req_msg = string.replace(auth_req_msg,'\012','')
webservice = httplib.HTTPConnection(ip_host)
webservice.putrequest("POST", "/idc/idcplg")
webservice.putheader("Content-length", "%d" % len(request))
webservice.putheader('Authorization', 'NTLM'+' '+auth_req_msg)
webservice.endheaders()
resp = webservice.getresponse()
resp.read()
challenge = resp.msg.get('WWW-Authenticate')
challenge_dec = base64.decodestring(challenge.split()[1])
msg3 = ntlm_gen.create_challenge_response(challenge_dec)
webservice = httplib.HTTP(ip_host)
webservice.putrequest("POST", "/idc/idcplg?IdcService=LOGIN&Auth=Intranet")
webservice.putheader("Host", SHOD)
webservice.putheader("Content-length", "%d" % len(request))
webservice.putheader('Authorization', 'NTLM'+' '+msg3)
webservice.putheader("Content-type", "text/xml; charset=\"UTF-8\"")
webservice.putheader("SOAPAction", "\"\"")
webservice.endheaders()
webservice.send(request)
statuscode, statusmessage, header = webservice.getreply()
res = webservice.getfile().read()
res_file = file('result.txt','wb')
res_file.write(res)
res_file.close()
sspi.py可以在这里找到: https://ironpython.svn.codeplex.com/svn/IronPython_Main/External.LCA_RESTRICTED/Languages/IronPython/27/Lib/site-packages/win32/lib/sspi.py
谢谢!
2 个回答
16
我找到了问题所在。
我应该保持连接不断开。
这就是关键!
现在这个问题解决了。
class WindoewNtlmMessageGenerator:
def __init__(self,user=None):
import win32api,sspi
if not user:
user = win32api.GetUserName()
self.sspi_client = sspi.ClientAuth("NTLM",user)
def create_auth_req(self):
import pywintypes
output_buffer = None
error_msg = None
try:
error_msg, output_buffer = self.sspi_client.authorize(None)
except pywintypes.error:
return None
auth_req = output_buffer[0].Buffer
auth_req = base64.b64encode(auth_req)
return auth_req
def create_challenge_response(self,challenge):
import pywintypes
output_buffer = None
input_buffer = challenge
error_msg = None
try:
error_msg, output_buffer = self.sspi_client.authorize(input_buffer)
except pywintypes.error:
return None
response_msg = output_buffer[0].Buffer
response_msg = base64.b64encode(response_msg)
return response_msg
SHOD='qqq.yyy.dev'
answer='result.xml'
fname='request.xml'
try:
a_file = open(fname, 'r')
f=open(fname, 'r')
except IOError:
sys.exit()
size = os.path.getsize(fname)
i=0
for line in f:
i=i+1
count_string=i
f.close()
size=size-count_string+1
print '1'
try:
webservice = httplib.HTTPConnection(SHOD)
webservice.putrequest("POST", "/idc/idcplg?IdcService=LOGIN&Auth=Intranet")
webservice.putheader("Content-length", "%d" % 0)
webservice.putheader("Content-type", "text/xml")
#webservice.putheader("User-Agent", 'Python-urllib/2.6')
webservice.endheaders()
res=webservice.getresponse()
except:
msg= "unable to connect to URL: "+ SHOD
sys.exit()
if res.status == 401:
auth_methods = [s.strip() for s in
res.msg.get('WWW-Authenticate').split(",")]
print auth_methods
if res.status <> 401:
msg= "unable to connect to URL: "+ SHOD_
log_error(msg,answer)
sys.exit()
print '2'
ntlm_gen = WindoewNtlmMessageGenerator()
auth_req_msg = ntlm_gen.create_auth_req()
webservice.putrequest("POST", "/idc/idcplg?IdcService=LOGIN&Auth=Intranet")
webservice.putheader("Content-length", "%d" % 0)
webservice.putheader("Connection", "Keep-Alive")
#webservice.putheader("User-Agent", 'Python-urllib/2.6')
webservice.putheader('Authorization', 'NTLM'+' '+auth_req_msg)
webservice.endheaders()
resp = webservice.getresponse()
resp.read()
print resp.status
challenge = resp.msg.get('WWW-Authenticate')
challenge_dec = base64.b64decode(challenge.split()[1])
print '3'
msg3 = ntlm_gen.create_challenge_response(challenge_dec)
webservice.putrequest("POST", "/idc/idcplg?IdcService=LOGIN&Auth=Intranet")
webservice.putheader("Content-type", "text/xml; charset=UTF-8")
webservice.putheader("Content-length", "%d" %(size))
webservice.putheader("Connection", "Close")
webservice.putheader('Authorization', 'NTLM'+' '+msg3)
#webservice.putheader("User-Agent", 'Python-urllib/2.6')
webservice.endheaders()
sable = a_file.read()
webservice.send(sable)
resp = webservice.getresponse()
res=resp.read()
26
import win32com.client
url = 'https://....'
h = win32com.client.Dispatch('WinHTTP.WinHTTPRequest.5.1')
h.SetAutoLogonPolicy(0)
h.Open('GET', url, False)
h.Send()
result = h.responseText
result
当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。