使用Python的HTTPBasicAuthHandler进行Bitbucket API认证

3 投票
4 回答
5647 浏览
提问于 2025-04-15 21:47

我正在尝试通过Bitbucket的API获取一个私有仓库的问题列表。

我已经确认使用hurl时,HTTP基本认证是有效的,但我在Python中无法进行认证。我参考了这个教程,写了以下脚本。

import cookielib
import urllib2

class API():
    api_url = 'http://api.bitbucket.org/1.0/'

    def __init__(self, username, password):
        self._opener = self._create_opener(username, password)

    def _create_opener(self, username, password):
        cj = cookielib.LWPCookieJar()
        cookie_handler = urllib2.HTTPCookieProcessor(cj)
        password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
        password_manager.add_password(None, self.api_url, username, password)
        auth_handler = urllib2.HTTPBasicAuthHandler(password_manager)
        opener = urllib2.build_opener(cookie_handler, auth_handler)
        return opener

    def get_issues(self, username, repository):
        query_url = self.api_url + 'repositories/%s/%s/issues/' % (username, repository)
        try:
            handler = self._opener.open(query_url)
        except urllib2.HTTPError, e:
            print e.headers
            raise e
        return handler.read()

api = API(username='my_username', password='XXXXXXXX')

api.get_issues('my_username', 'my_repository') 的结果是:

>>> 
Server: nginx/0.7.62
Date: Mon, 19 Apr 2010 16:15:06 GMT
Content-Type: text/plain
Connection: close
Vary: Authorization,Cookie
Content-Length: 9

Traceback (most recent call last):
  File "C:/USERS/personal/bitbucket-burndown/bitbucket-api.py", line 29, in <module>
    print api.get_issues('my_username', 'my_repository')
  File "C:/USERS/personal/bitbucket-burndown/bitbucket-api.py", line 25, in get_issues
    raise e
HTTPError: HTTP Error 401: UNAUTHORIZED

api.get_issues('jespern', 'bitbucket') 则运行得非常顺利。

我的代码哪里出了问题呢?

4 个回答

1

看看这个叫做 python-bitbucket 的东西,它是一个用来和 Bitbucket 的 API 进行互动的 Python 工具。原来的库(original library)只能用来读取数据,但 ericof 加入了身份验证和一些写入权限,我在这基础上进行了扩展,你可以在这里找到我改进的版本:https://bitbucket.org/bkmontgomery/python-bitbucket

你可以用下面的方式从一个私有仓库中获取问题:

import bitbucket

bb = bitbucket.BitBucket(username='your-username', password='secret')
repo = bb.repository('your-username', 'your-private-repo')
issues = repo.issues()
2

我觉得Python的HTTPBasicAuthHandler没有错误。基本认证通常是这样的过程:

  • 客户端发出请求时没有提供凭证;
  • 服务器返回401错误;
  • 客户端再次发送请求,这次带上凭证;
  • 服务器返回内容。

在BitBucket的情况下,流程是这样的:

  • 客户端发出请求时没有提供凭证;
  • BitBucket直接返回一个公共仓库的列表。

BitBucket从来不会发出401错误,所以Python也就不会发送凭证。

如果你想看看一个不使用cookies就能在BitBucket上进行认证的例子,可以看看这个链接:

5

看起来 HTTPBasicAuthHandler 这个东西有点问题。下面的代码可以正常运行:

class API():
    api_url = 'http://api.bitbucket.org/1.0/'

    def __init__(self, username, password, proxy=None):
        encodedstring = base64.encodestring("%s:%s" % (username, password))[:-1]
        self._auth = "Basic %s" % encodedstring
        self._opener = self._create_opener(proxy)

    def _create_opener(self, proxy=None):
        cj = cookielib.LWPCookieJar()
        cookie_handler = urllib2.HTTPCookieProcessor(cj)
        if proxy:
            proxy_handler = urllib2.ProxyHandler(proxy)
            opener = urllib2.build_opener(cookie_handler, proxy_handler)
        else:
            opener = urllib2.build_opener(cookie_handler)
        return opener

    def get_issues(self, username, repository):
        query_url = self.api_url + 'repositories/%s/%s/issues/' % (username, repository)
        try:
            req = urllib2.Request(query_url, None, {"Authorization": self._auth })
            handler = self._opener.open(req)
        except urllib2.HTTPError, e:
            print e.headers
            raise e
        return json.load(handler)

撰写回答