带有HTTPS和HTTP认证的pywikipedia机器人
我在让我的机器人登录公司内部网的MediaWiki时遇到了麻烦。我觉得这可能是因为维基被HTTP认证保护了。
以下是一些事实:
- 维基的根地址是:https://local.example.com/mywiki/
- 当我用浏览器访问这个维基时,会弹出一个窗口要求输入企业凭证(我猜这就是基本的访问认证)
这是我在user-config.py文件里的内容:
mylang = 'en'
family = 'mywiki'
usernames['mywiki']['en'] = u'Bot'
authenticate['local.example.com'] = ('user', 'pass')
这是我在mywiki_family.py文件里的内容:
# -*- coding: utf-8 -*-
import family, config
# The Wikimedia family that is known as mywiki
class Family(family.Family):
def __init__(self):
family.Family.__init__(self)
self.name = 'mywiki'
self.langs = { 'en' : 'local.example.com'}
def scriptpath(self, code):
return '/mywiki'
def version(self, code):
return '1.13.5'
def isPublic(self):
return False
def hostname(self, code):
return 'local.example.com'
def protocol(self, code):
return 'https'
def path(self, code):
return '/mywiki/index.php'
当我执行login.py -v -v时,得到的结果是:
urllib2.urlopen(urllib2.Request('https://local.example.com/w/index.php?title=Special:Userlogin&useskin=monobook&action=submit', wpSkipCookieCheck=1&wpPassword=XXXX&wpDomain=&wpRemember=1&wpLoginattempt=Aanmelden%20%26%20Inschrijven&wpName=Bot, {'Content-type': 'application/x-www-form-urlencoded', 'User-agent': 'PythonWikipediaBot/1.0'})):
(Redundant traceback info here)
urllib2.HTTPError: HTTP Error 401: Unauthorized
(我不太明白为什么它显示的是'local.example.com/w'而不是'/mywiki'。)
我以为它可能是在尝试向example.com认证,而不是example.com/wiki,所以我把认证那一行改成了:
authenticate['local.example.com/mywiki'] = ('user', 'pass')
但是我却收到了来自IIS的HTTP 401.2错误:
您没有权限使用您提供的凭证查看此目录或页面,因为您的网页浏览器发送了一个WWW-Authenticate头字段,而Web服务器没有配置为接受它。
如果有人能帮我解决这个问题,我将非常感激。
更新 在修复了我的family文件后,现在显示:
获取网站mywiki:en的信息 ('http错误', 401, '未授权', ) 警告:无法打开'https://local.example.com/mywiki/index.php?title=Non-existing_page&action=edit&useskin=monobook'。也许服务器或您的连接出现了问题。1分钟后重试...
我查看了一个普通的urllib2.urlopen调用的HTTP头,发现它使用的是WWW-Authenticate: Negotiate和WWW-Authenticate: NTLM。我在想urllib2和pywikipedia是否不支持这个?
更新 为帮助我解决这个问题增加了一个丰厚的悬赏。我可以使用python-ntlm进行认证。请问我该如何将其集成到pywikipedia中?
2 个回答
我猜你的问题是服务器需要基本认证,但你的客户端没有处理这个认证。Michael Foord 写了一篇不错的文章,讲的是如何在 Python 中处理 基本认证。
你没有提供足够的信息让我确认这个问题,所以如果这样做不行,请提供一些额外的信息,比如你连接尝试时的网络数据记录。
首先,login.py
试图访问 '\w' 而不是你的路径,这说明你的家庭配置有问题。
你的代码缩进得很奇怪:scriptpath
是新 Family 类的成员吗?就像这样:
class Family(family.Family):
def __init__(self):
family.Family.__init__(self)
self.name = 'mywiki'
self.langs = { 'en' : 'local.example.com'}
def scriptpath(self, code):
return '/mywiki'
def version(self, code):
return '1.13.5'
def isPublic(self):
return False
def hostname(self, code):
return 'local.example.com'
def protocol(self, code):
return 'https'
?
我觉得你的家庭文件有问题。检查的方法很简单,可以在 Python 控制台里输入:
import wikipedia
site = wikipedia.getSite('en', 'mywiki')
print site.login_address()
只要相对地址不对,显示的是 '/w' 而不是 '/mywiki',就说明家庭文件还没有正确配置,这样机器人就无法正常工作了 :)
更新:如何在 pywikipedia 中集成 ntlm?
我刚看了下基本示例,在这里。我会在 login.py
中那行代码之前集成这段代码:
response = urllib2.urlopen(urllib2.Request(self.site.protocol() + '://' + self.site.hostname() + address, data, headers))
你想写的内容大概是这样的:
from ntlm import HTTPNtlmAuthHandler
user = 'DOMAIN\User'
password = "Password"
url = self.site.protocol() + '://' + self.site.hostname()
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, url, user, password)
# create the NTLM authentication handler
auth_NTLM = HTTPNtlmAuthHandler.HTTPNtlmAuthHandler(passman)
# create and install the opener
opener = urllib2.build_opener(auth_NTLM)
urllib2.install_opener(opener)
response = urllib2.urlopen(urllib2.Request(self.site.protocol() + '://' + self.site.hostname() + address, data, headers))
我会测试这个,并直接将其集成到 pywikipedia 的代码库中,只要我有可用的 ntlm 设置...
无论发生什么,请不要把你的解决方案藏起来:我们在 pywikipedia 非常感兴趣你的解决方案 :)