2012-01-10 2 views
4

Я пытаюсь найти, как я могу использовать обычную проверку подлинности с помощью urllib2 в питона, чтобы получить выпуск KEY The JIRA REST API описывает Ури доступныеБазовая аутентификация с использованием urllib2 с питоном с JIRA REST API

Спасибо за sugestions, я буду попробовать, тем временем, я просто хотел обновить это с моим собственным усилием: Вот пример кода Python я пробовал:

import urllib2, sys, re, base64 
from urlparse import urlparse 
theurl = 'http://my.rest-server.com:8080/rest/api/latest/AA-120'   # if you want to run this example you'll need to supply a protected page with y 
our username and password 
username = 'username' 
password = 'password'   # a very bad password 

req = urllib2.Request(theurl) 
print req 
try: 
    handle = urllib2.urlopen(req) 
    print handle 
except IOError, e:     # here we are assuming we fail 
    pass 
else:        # If we don't fail then the page isn't protected 
    print "This page isn't protected by authentication." 
    sys.exit(1) 
if not hasattr(e, 'code') or e.code != 401:     # we got an error - but not a 401 error 
    print "This page isn't protected by authentication." 
    print 'But we failed for another reason.' 
    sys.exit(1) 

authline = e.headers.get('www-authenticate', '')    # this gets the www-authenticat line from the headers - which has the authentication 
scheme and realm in it 
if not authline: 
    print 'A 401 error without an authentication response header - very weird.' 
    sys.exit(1) 
authobj = re.compile(r'''(?:\s*www-authenticate\s*:)?\s*(\w*)\s+realm=['"](\w+)['"]''', re.IGNORECASE)   # this regular expression is used to 
extract scheme and realm 
matchobj = authobj.match(authline) 
if not matchobj:          # if the authline isn't matched by the regular expression then something is wrong 
    print 'The authentication line is badly formed.' 
    sys.exit(1) 
scheme = matchobj.group(1) 
print scheme 
realm = matchobj.group(2) 
print realm 
if scheme.lower() != 'basic': 
    print 'This example only works with BASIC authentication.' 
    sys.exit(1) 

base64string = base64.encodestring('%s:%s' % (username, password))[:-1] 
authheader = "Basic %s" % base64string 
req.add_header("Authorization", authheader) 
try: 
    handle = urllib2.urlopen(req) 
except IOError, e:     # here we shouldn't fail if the username/password is right 
    print "It looks like the username or password is wrong." 
    sys.exit(1) 
thepage = handle.read() 
server = urlparse(theurl)[1].lower()   # server names are case insensitive, so we will convert to lower case 
test = server.find(':') 
if test != -1: server = server[:test]   # remove the :port information if present, we're working on the principle that realm names per serve 
r are likely to be unique... 

passdict = {(server, realm) : authheader }  # now if we get another 401 we can test for an entry in passdict before having to ask the user for a 
username/password 

print 'Done successfully - information now stored in passdict.' 
print 'The webpage is stored in thepage.' 

--- и я получаю результат: Эта страница не защищена аутентификация. Но мы потерпели неудачу по другой причине.

тогда страница защищена аутентификацией

Я попытался установить запросы, но получила сообщение об ошибке:

sudo easy_install requests 
Searching for requests 
Reading http://pypi.python.org/simple/requests/ 

Reading https://github.com/kennethreitz/requests 
Reading http://python-requests.org 
Best match: requests 0.9.1 
Downloading http://pypi.python.org/packages/source/r/requests/requests-0.9.1.tar.gz#md5=8ed4667edb5d57945b74a9137adbb8bd 
Processing requests-0.9.1.tar.gz 
Running requests-0.9.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-lTQu8K/requests-0.9.1/egg-dist-tmp-M2yQCt 
Traceback (most recent call last): 
    File "/usr/bin/easy_install", line 7, in ? 
    sys.exit(
    File "/usr/lib/python2.4/site-packages/setuptools-0.6c12dev_r88846-py2.4.egg/setuptools/command/easy_install.py", line 1712, in main 
    with_ei_usage(lambda: 
    File "/usr/lib/python2.4/site-packages/setuptools-0.6c12dev_r88846-py2.4.egg/setuptools/command/easy_install.py", line 1700, in with_ei_usage 
    return f() 
    File "/usr/lib/python2.4/site-packages/setuptools-0.6c12dev_r88846-py2.4.egg/setuptools/command/easy_install.py", line 1716, in <lambda> 
    distclass=DistributionWithoutHelpCommands, **kw 
    File "/usr/lib64/python2.4/distutils/core.py", line 149, in setup 
    dist.run_commands() 
    File "/usr/lib64/python2.4/distutils/dist.py", line 946, in run_commands 
    self.run_command(cmd) 
    File "/usr/lib64/python2.4/distutils/dist.py", line 966, in run_command 
    cmd_obj.run() 
    File "/usr/lib/python2.4/site-packages/setuptools-0.6c12dev_r88846-py2.4.egg/setuptools/command/easy_install.py", line 211, in run 
    self.easy_install(spec, not self.no_deps) 
    File "/usr/lib/python2.4/site-packages/setuptools-0.6c12dev_r88846-py2.4.egg/setuptools/command/easy_install.py", line 446, in easy_install 
    return self.install_item(spec, dist.location, tmpdir, deps) 
    File "/usr/lib/python2.4/site-packages/setuptools-0.6c12dev_r88846-py2.4.egg/setuptools/command/easy_install.py", line 476, in install_item 
    dists = self.install_eggs(spec, download, tmpdir) 
    File "/usr/lib/python2.4/site-packages/setuptools-0.6c12dev_r88846-py2.4.egg/setuptools/command/easy_install.py", line 655, in install_eggs 
    return self.build_and_install(setup_script, setup_base) 
    File "/usr/lib/python2.4/site-packages/setuptools-0.6c12dev_r88846-py2.4.egg/setuptools/command/easy_install.py", line 930, in build_and_install 
    self.run_setup(setup_script, setup_base, args) 
    File "/usr/lib/python2.4/site-packages/setuptools-0.6c12dev_r88846-py2.4.egg/setuptools/command/easy_install.py", line 919, in run_setup 
    run_setup(setup_script, args) 
    File "/usr/lib/python2.4/site-packages/setuptools-0.6c12dev_r88846-py2.4.egg/setuptools/sandbox.py", line 61, in run_setup 
    DirectorySandbox(setup_dir).run(
    File "/usr/lib/python2.4/site-packages/setuptools-0.6c12dev_r88846-py2.4.egg/setuptools/sandbox.py", line 105, in run 
    return func() 
    File "/usr/lib/python2.4/site-packages/setuptools-0.6c12dev_r88846-py2.4.egg/setuptools/sandbox.py", line 64, in <lambda> 
    {'__file__':setup_script, '__name__':'__main__'} 
    File "setup.py", line 6, in ? 
    File "/tmp/easy_install-lTQu8K/requests-0.9.1/requests/__init__.py", line 26 
    from . import utils 
     ^
SyntaxError: invalid syntax 
+0

Специально для Jira я бы рекомендовал смотреть на питон JIRA апи обертку пакета на PyPI: https://pypi.python.org/pypi/jira – ThorSummoner

ответ

4

Забавный, я работал над этим вчера для JIRA Python CLI. Я использовал подход REST API для получения файла cookie для проверки подлинности и специального открывателя. В приведенном ниже примере показано использование переносного устройства для отправки данных на страницу для добавления компонента, но вы можете заменить это на вызов правильного URL-адреса для другого вызова REST.

""" 
Demonstration of using Python for a RESTful call to JIRA 

Matt Doar 
CustomWare 
""" 

import urllib 
import urllib2 
import cookielib 

jira_serverurl = "http://jira.example.com:8080" 
creds = { "username" : "admin", "password" : "admin" } 
authurl = jira_serverurl + "/rest/auth/latest/session" 

# Get the authentication cookie using the REST API 
cj = cookielib.CookieJar() 
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) 
req = urllib2.Request(authurl) 
req.add_data('{ "username" : "admin", "password" : "admin" }') 
req.add_header("Content-type", "application/json") 
req.add_header("Accept", "application/json") 
fp = opener.open(req) 
fp.close() 

add_component_url = jira_serverurl + "/secure/project/AddComponent.jspa?pid=10020&name=ABC4" 
print "Using %s" % (add_component_url) 

# Have to add data to make urllib2 send a POST 
values = {} 
data = urllib.urlencode(values) 

# Have to tell JIRA to not use a form token 
headers = {'X-Atlassian-Token': 'no-check'} 

request = urllib2.Request(add_component_url, data, headers=headers) 
fp = opener.open(request) 

print fp.read() 
+0

Гоша, мне не нравится макрос кода для этого редактора. Дайте мне разметку! – mdoar

+0

Привет Matt, Попробуйте "CNTRL + K", после выбора части кода – kamal

+0

Matt, я не мог понять значение PID и имя часть, в dd_component_url = jira_serverurl + «/secure/project/AddComponent.jspa?pid= 10020 & name = ABC4 " – kamal

6

Я бы рекомендовал с учетом использования очень отличная requests библиотеки, которая обеспечивает хорошую абстракцию, чтобы сделать urllib2 немного проще в использовании.

С requests вы можете просто сделать:

r = requests.get('https://api.github.com', auth=('user', 'pass')) 

Он поддерживает все методы запросов, необходимых, чтобы сделать REST звонки, а также (POST, PUT, DELETE, и т.д ...).

Вы можете найти больше здесь:

http://pypi.python.org/pypi/requests


Если вы абсолютно MUST использовать обычный старый urllib2, вот пример того, как это можно сделать:

import urllib2 

theurl = 'http://www.someserver.com/toplevelurl/somepage.htm' 
username = 'johnny' 
password = 'XXXXXX' 

passman = urllib2.HTTPPasswordMgrWithDefaultRealm() 
passman.add_password(None, theurl, username, password) 
# because we have put None at the start it will always 
# use this username/password combination for urls 
# for which `theurl` is a super-url 

authhandler = urllib2.HTTPBasicAuthHandler(passman) 

opener = urllib2.build_opener(authhandler) 

urllib2.install_opener(opener) 
# All calls to urllib2.urlopen will now use our handler 
# Make sure not to include the protocol in with the URL, or 
# HTTPPasswordMgrWithDefaultRealm will be very confused. 
# You must (of course) use it when fetching the page though. 

pagehandle = urllib2.urlopen(theurl) 
# authentication is now handled automatically for us 

Подробнее можно найти здесь: http://www.voidspace.org.uk/python/articles/authentication.shtml

+0

Не отвечая на вопрос прямо, но я как раз собирался предложить проверку out 'request'. @kamal, даже если вы не используете 'запросы', вы обязательно должны проверить модуль. – istruble

+0

Спасибо @istruble – kamal

1

У меня была такая же проблема с доступом к Jira REST. Вот что работает для меня:

class JiraOpenerWrapper(object): 
    # Class to wrap urllib2 OpenerDirector to add authenication headers. 
    # this is needed fro Jira - see comment below. 
    def __init__(self, opener, user, password): 
    self.opener = opener 
    self.user = user 
    self.password = password 

    def open(self, url, data, timeout): 
    if isinstance(url, str): 
     # if given a url - create a request and add 
     req = urllib2.Request(url, data, { 
         "Authorization": 
         "Basic " + base64.b64encode(
          self.user + ":" + self.password) 
        }) 
    else: 
     req = url 
    return self.opener.open(req, data, timeout) 

    def __getattr__(self, attr): 
    if attr == "open": 
     return self.open 
    return getattr(self.opener, attr) 


def RegisterPasswords(user, password): 
    password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() 
    password_manager.add_password(
    None, 'https://rt.mycorp.site/', user, password) 
    password_manager.add_password(
    None, 'https://jira.mycorp.site/', user, password) 
    auth_handler = urllib2.HTTPBasicAuthHandler(password_manager) 
    opener = urllib2.build_opener(auth_handler) 
    # Jira has a strage behviour - it does not return the proper error 
    # when sending a request without an Authentication header. 
    # This causes Python's urllib2 not to retry with the pass word. 
    # For Jira we would need to add the headers all the time 
    jira_opener = JiraOpenerWrapper(opener, user, password) 
    urllib2.install_opener(jira_opener) 


def GameJira(): 
    url = "https://jira.mycorp.site/rest/api/2/issue/PRJ-123" 

    data = urllib2.urlopen(url, None).read() 
    print "Jira:\n", data 
+0

Из всех решений здесь этот был единственным, который работал для меня с JIRA 6.2 (хотя я не пробовал библиотеку запросов). – Jamie

2

я имел лучший успех, используя requests module.

import requests 

jira_session = requests.session() 

try: 
    jira_session.post('https://server', auth=(user, password), verify=False) 
except: 
    print('Unable to connect or authenticate with JIRA server.') 

url = 'https://server/rest/api/2/search?jql=project="ABCXYZ"&maxResults=100' 
results = jira_session.get(url) 
project_data = results.json() 
Смежные вопросы