2010-06-03 72 views
18

Tôi đang cố triển khai xác thực NTLM trên IIS (Windows Server 2003) từ Windows 7 bằng python. Cấp độ xác thực người quản lý mạng LAN: Chỉ gửi phản hồi NTLM.
Máy khách và máy chủ nằm trong cùng một miền.
Bộ điều khiển miền (AD) nằm trên máy chủ khác (cũng chạy Windows Server 2003).Xác thực NTLM bằng Python

Tôi nhận được 401.1 - Không được ủy quyền: Quyền truy cập bị từ chối do thông tin đăng nhập không hợp lệ. Bạn có thể vui lòng giúp tôi tìm hiểu điều gì sai với mã này và/hoặc chỉ cho tôi các hướng dẫn có thể khác để giải quyết vấn đề này (bằng cách sử dụng NTLM hoặc 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 có sẵn ở đây: https://ironpython.svn.codeplex.com/svn/IronPython_Main/External.LCA_RESTRICTED/Languages/IronPython/27/Lib/site-packages/win32/lib/sspi.py

Cảm ơn!

Trả lời

14

Tôi đã phát hiện ra điều gì đã xảy ra. Tôi nên giữ kết nối còn sống. Đó là hàng hóa! Bây giờ vấn đề này được giải quyết.

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() 
+14

Bạn nên đánh dấu câu trả lời này là chấp nhận (nhấp vào dấu kiểm màu xanh bên cạnh nó) vì vậy nó không được liệt kê như là một câu hỏi chưa được trả lời. –

+2

Tính năng này hoạt động như thế nào đối với Linux? (Tôi tin rằng một số thư viện không có sẵn) – Dimitris

+0

@Dimitris: nó sử dụng các hàm Windows nguyên bản để xác thực đối với miền - không có cách nào để thực hiện điều đó từ một hộp không phải Windows. Bạn sẽ phải thực hiện lại giao thức Netlogon (MS-NRPC) một cách tự nhiên, bao gồm việc triển khai lớp MS-RPC bên dưới. Không có nhiều niềm vui. – bobince

17
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 
+1

Câu trả lời này là rất tốt. Nó làm việc cho tôi! Tôi đang ở trong môi trường Windows và muốn sử dụng xác thực miền. Nó hoạt động !!! – vy32

+0

còn yêu cầu POST thì sao? Tôi tự hỏi làm thế nào tôi có thể xử lý các tham số trong chức năng mở ... –

Các vấn đề liên quan