之前帮公司爬取过内部的一个问题单网站,要求将每个问题单的下的附件下载下来。一开始的时候我就遇到一个破解登陆验证的大坑...... (╬ ̄皿 ̄)=○
由于在公司使用的都是内网,代码和网站的描述也都属于公司的信息安全资产范围,具体细节不方便透露,就简要描述一下需求和问题吧。
在访问网站前需要先进行一个登陆,浏览器使用的是chrome,一开始我的想法是通过chromrdriver模拟登陆,但是用户名和密码输入框都是使用的浏览器自带的弹窗,chromedriver无法获取到输入和点击位置。放弃这个想法后我就想着模拟一个请求头去发送请求破解的方式,但是直接F12后还是没法从头信息中获取到登陆验证的方式。。。。由于之前压根没接触过爬虫,对前端知识和网络协议也不太了解,当场直接自闭了!!!
皇天不负有心人,最后通过Fiddler抓包,终于获取到了登陆验证的方式。网站是通过ntml方式来验证登陆的。废话不多说直接上代码(网址和账号密码信息请自行修改)
# -*- coding:utf-8 -*-
# author: cdc
# date: 2019/1/20 import ntlm3
import urllib.request def login(url,username,password):
passman = urllib.request.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None,url,username,password)
auth_NTLM = ntlm3.HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passman)
opener = urllib.request.build_opener(auth_NTLM)
urllib.request.install_opener(opener)
response = urllib.request.urlopen(url)
return response if __name__ == "__main__":
url = r'http://dts.huawei.com'
username = 'cwx589809'
password = 'cdc19951216tr,!'
res = login(url,username,password)
print(res)
但是还是无法破解登陆问题,获取的返回信息状态还是400。是的,忙活了半天我再一次自闭了!!!
再一次在发送登陆请求的时候用Fiddler去抓包,发现auth_header值中有字段'negotiate',而我又对比了下python-ntml3中的源码,返现python-ntml3库中AbstractNtlmAuthHandler类的http_error_authentication_required方法中并没有对这个值进行判断。
源码:
将这一行的代码改成:
if auth_header_value is not None and (
'ntlm' in auth_header_value.lower() or 'negotiate' in auth_header_value.lower()):
此外,网页返回的信息都是string类型的,而源码中统一处理的都是bytes对象,因此还需对源码的两处进行一个解码的操作
源码:
将这两处改为:
# line_num:58
auth = 'NTLM %s' % bytes.decode(ntlm.create_NTLM_NEGOTIATE_MESSAGE(user, type1_flags)) # line_num:108
auth = 'NTLM %s' % bytes.decode(ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, UserName, DomainName, pw, NegotiateFlags))
小结一下:
首先这个只是针对我们公司内部开发的网站的一个问题,其他网站的auth_header或许只有'ntml'或者其他的值,这个需要大家自己根据实际的需求去修改;
其次或许还有其他的更好的破解此类登陆的方式,也希望大家一起学习分享(鄙人刚入门小白一个)。
PS:Fiddler真尼玛好用,抓包神器名不虚传!
完结撒花,掰掰!