Вход в сервер аутентификации SAML/Shibboleth с использованием python
Я пытаюсь войти в свой университетский сервер через python, но я совершенно не уверен, как идти о создании соответствующих HTTP POST, создавая ключи и сертификаты, а также другие части процесса, которые могут быть незнакомы с этим должны соответствовать спецификации SAML. Я могу войти в мой браузер просто отлично, но я хотел бы иметь возможность входа и доступа к другому содержимому на сервере с помощью python.
Для справки вот сайт
Я пробовал войти в систему, используя механизацию (выбор формы, заполнение полей, нажатие кнопки кнопки отправки через mechanize.Broswer.submit() и т.д.) безрезультатно; сайт входа в систему каждый раз отбрасывается.
В этот момент я открыт для реализации решения в зависимости от того, какой язык наиболее подходит для этой задачи. В принципе, я хочу программно войти на сервер, прошедший проверку на SAML.
Ответы
Ответ 1
В основном то, что вам нужно понять, это рабочий процесс за процессом проверки SALM. К сожалению, нет PDF файла, который, по-видимому, действительно помогает найти способы, которые браузер делает при доступе к сайту, защищенному SAML.
Возможно, вы должны взглянуть на что-то вроде этого: http://www.docstoc.com/docs/33849977/Workflow-to-Use-Shibboleth-Authentication-to-Sign
и, очевидно, к этому: http://en.wikipedia.org/wiki/Security_Assertion_Markup_Language. В частности, сосредоточьте свое внимание на этой схеме:
![enter image description here]()
Что я сделал, когда пытался понять способ работы SAML, поскольку документация была , поэтому плохой, записывал (да, писал - на бумаге) все действия, которые выполнял браузер из от первого до последнего. Я использовал Opera, установив ее, чтобы не разрешить автоматические переадресации (код ответа 300, 301, 302 и т.д.), А также не включать Javascript.
Затем я записал все файлы cookie, которые сервер посылал мне, что делал и по какой причине.
Возможно, это было слишком много усилий, но таким образом я смог написать библиотеку на Java, которая подходит для работы, и невероятно быстро и эффективно. Может быть, когда-нибудь я выпущу его публично...
Что вы должны понимать, так это то, что в логике SAML есть два игрока: IDP (поставщик удостоверений) и SP (поставщик услуг).
A. ПЕРВЫЙ ШАГ: пользовательский агент запрашивает ресурс для SP
Я уверен, что вы достигли ссылки, которую вы ссылаетесь в своем вопросе, с другой страницы, нажимая на что-то вроде "Доступ к защищенному веб-сайту". Если уделить больше внимания, вы заметите, что следующая ссылка: не та, в которой отображается форма проверки подлинности. Это потому, что нажатие ссылки с IDP на SP является шагом для SAML. Первый шаг, актуален.
Это позволяет IDP определять, кто вы, и почему вы пытаетесь получить доступ к его ресурсу.
Итак, в основном вам нужно сделать запрос на ссылку, которую вы следовали, чтобы получить веб-форму, и получить куки файлы, которые он установит. То, что вы не увидите, это строка SAMLRequest, закодированная в перенаправлении 302, которую вы найдете за ссылкой, отправленной IDP, создающему соединение.
Я думаю, что это причина, по которой вы не можете механизировать весь процесс. Вы просто подключились к форме, без идентификации идентификации!
В. ВТОРОЙ ЭТАП: заполнение формы и отправка ее
Это легко. Пожалуйста, будь осторожен! Куки, которые сейчас, не совпадают с приведенными выше файлами. Теперь вы подключаетесь к совершенно другому сайту. Это причина, по которой используется SAML: разные веб-сайты, те же учетные данные.
Таким образом, вы можете захотеть сохранить эти файлы cookie аутентификации, предоставленные успешным логином, другой переменной.
IDP теперь отправит вам ответ (после SAMLRequest): SAMLResponse. Вы должны обнаружить, что он получает исходный код веб-страницы, на которую заканчивается вход. Фактически, эта страница представляет собой большую форму, содержащую ответ, с некоторым кодом в JS, который автоматически подчиняет его, когда страница загружается. Вы должны получить исходный код страницы, проанализировать его, чтобы избавиться от всех неиспользуемых материалов HTML и получить SAMLResponse (зашифрованный).
С. THIRD STEP: отправка ответа на SP
Теперь вы готовы завершить процедуру. Вы должны отправить (через POST, поскольку вы эмулируете форму), SAMLResponse получен на предыдущем шаге, в SP. Таким образом, он предоставит файлы cookie, необходимые для доступа к защищенным материалам, к которым вы хотите получить доступ.
Aaaaand, все готово!
Опять же, я думаю, что самое ценное, что вам нужно будет сделать, это использовать Opera и анализировать ВСЕ все перенаправления SAML. Затем скопируйте их в свой код. Это не так сложно, просто имейте в виду, что IDP совершенно отличается от SP.
Ответ 2
Селен с безголовым веб-сайтом PhantomJS будет вашим лучшим выбором для входа в Shibboleth, потому что он обрабатывает файлы cookie и даже Javascript для вас.
Установка:
$ pip install selenium
$ brew install phantomjs
from selenium import webdriver
from selenium.webdriver.support.ui import Select # for <SELECT> HTML form
driver = webdriver.PhantomJS()
# On Windows, use: webdriver.PhantomJS('C:\phantomjs-1.9.7-windows\phantomjs.exe')
# Service selection
# Here I had to select my school among others
driver.get("http://ent.unr-runn.fr/uPortal/")
select = Select(driver.find_element_by_name('user_idp'))
select.select_by_visible_text('ENSICAEN')
driver.find_element_by_id('IdPList').submit()
# Login page (https://cas.ensicaen.fr/cas/login?service=https%3A%2F%2Fshibboleth.ensicaen.fr%2Fidp%2FAuthn%2FRemoteUser)
# Fill the login form and submit it
driver.find_element_by_id('username').send_keys("myusername")
driver.find_element_by_id('password').send_keys("mypassword")
driver.find_element_by_id('fm1').submit()
# Now connected to the home page
# Click on 3 links in order to reach the page I want to scrape
driver.find_element_by_id('tabLink_u1240l1s214').click()
driver.find_element_by_id('formMenu:linknotes1').click()
driver.find_element_by_id('_id137Pluto_108_u1240l1n228_50520_:tabledip:0:_id158Pluto_108_u1240l1n228_50520_').click()
# Select and print an interesting element by its ID
page = driver.find_element_by_id('_id111Pluto_108_u1240l1n228_50520_:tableel:tbody_element')
print page.text
Примечание:
- во время разработки, используйте Firefox, чтобы просмотреть, что вы делаете
driver = webdriver.Firefox()
- этот script предоставляется как есть и с соответствующими ссылками, поэтому вы можете сравнить каждую строку кода с фактическим исходным кодом страниц (до логина как минимум).
Ответ 3
Расширение ответа от Stéphane Bruckert выше, как только вы использовали Selenium для получения файлов cookie, вы все равно можете переключиться на запросы, если хотите:
import requests
cook = {i['name']: i['value'] for i in driver.get_cookies()}
driver.quit()
r = requests.get("https://protected.ac.uk", cookies=cook)
Ответ 4
Вы можете найти здесь более подробное описание процесса аутентификации Shibboleth.
Ответ 5
Механизм также может выполнять работу, за исключением того, что не обрабатывает Javascript. Authentification успешно работала, но однажды на главной странице я не смог загрузить такую ссылку:
<a href="#" id="formMenu:linknotes1"
onclick="return oamSubmitForm('formMenu','formMenu:linknotes1');">
Если вам нужен Javascript, лучше используйте Selenium с PhantomJS. В противном случае, надеюсь, вы найдете вдохновение от этого script:
#!/usr/bin/env python
#coding: utf8
import sys, logging
import mechanize
import cookielib
from BeautifulSoup import BeautifulSoup
import html2text
br = mechanize.Browser() # Browser
cj = cookielib.LWPCookieJar() # Cookie Jar
br.set_cookiejar(cj)
# Browser options
br.set_handle_equiv(True)
br.set_handle_gzip(True)
br.set_handle_redirect(True)
br.set_handle_referer(True)
br.set_handle_robots(False)
# Follows refresh 0 but not hangs on refresh > 0
br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)
# User-Agent
br.addheaders = [('User-agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36')]
br.open('https://ent.unr-runn.fr/uPortal/')
br.select_form(nr=0)
br.submit()
br.select_form(nr=0)
br.form['username'] = 'myusername'
br.form['password'] = 'mypassword'
br.submit()
br.select_form(nr=0)
br.submit()
rs = br.open('https://ent.unr-runn.fr/uPortal/f/u1240l1s214/p/esup-mondossierweb.u1240l1n228/max/render.uP?pP_org.apache.myfaces.portlet.MyFacesGenericPortlet.VIEW_ID=%2Fstylesheets%2Fetu%2Fdetailnotes.xhtml')
# Eventually comparing the cookies with those on Live HTTP Header:
print "Cookies:"
for cookie in cj:
print cookie
# Displaying page information
print rs.read()
print rs.geturl()
print rs.info();
# And that last line didn't work
rs = br.follow_link(id="formMenu:linknotes1", nr=0)
Ответ 6
Я написал простой Python script, способный регистрироваться на странице Shibbolized.
Во-первых, я использовал Live HTTP Headers в Firefox, чтобы посмотреть перенаправления для конкретной страницы Shibbolized, на которую я нацелился.
Затем я написал простой script с помощью urllib.request
(в Python 3.4, но urllib2
в Python 2.x, похоже, имеет одинаковую функциональность). Я обнаружил, что перенаправление по умолчанию из urllib.request
работало для моих целей, однако мне было приятно подклассифицировать urllib.request.HTTPRedirectHandler
и в этом подклассе (класс ShibRedirectHandler
) добавить обработчик для всех событий http_error_302.
В этом подклассе я просто распечатывал значения параметров (для целей отладки); обратите внимание, что для использования последующей переадресации по умолчанию вам нужно закончить обработчик с помощью return HTTPRedirectHandler.http_error_302(self, args...)
(т.е. вызова обработчика базового класса http_errror_302.)
Самым важным компонентом, с помощью которого urllib
работает с Shibbolized Authentication, является создание OpenerDirector
, в котором добавлена обработка файлов cookie. Вы создаете OpenerDirector
со следующим:
cookieprocessor = urllib.request.HTTPCookieProcessor()
opener = urllib.request.build_opener(ShibRedirectHandler, cookieprocessor)
response = opener.open("https://shib.page.org")
Вот полный script, который может начать работу (вам нужно будет изменить несколько макетов URL, которые я предоставил, а также ввести правильное имя пользователя и пароль). Это использует классы Python 3; чтобы эта работа в Python2 заменила urllib.request на urllib2 и urlib.parse с urlparse:
import urllib.request
import urllib.parse
#Subclass of HTTPRedirectHandler. Does not do much, but is very
#verbose. prints out all the redirects. Compaire with what you see
#from looking at your browsers redirects (using live HTTP Headers or similar)
class ShibRedirectHandler (urllib.request.HTTPRedirectHandler):
def http_error_302(self, req, fp, code, msg, headers):
print (req)
print (fp.geturl())
print (code)
print (msg)
print (headers)
#without this return (passing parameters onto baseclass)
#redirect following will not happen automatically for you.
return urllib.request.HTTPRedirectHandler.http_error_302(self,
req,
fp,
code,
msg,
headers)
cookieprocessor = urllib.request.HTTPCookieProcessor()
opener = urllib.request.build_opener(ShibRedirectHandler, cookieprocessor)
#Edit: should be the URL of the site/page you want to load that is protected with Shibboleth
(opener.open("https://shibbolized.site.example").read())
#Inspect the page source of the Shibboleth login form; find the input names for the username
#and password, and edit according to the dictionary keys here to match your input names
loginData = urllib.parse.urlencode({'username':'<your-username>', 'password':'<your-password>'})
bLoginData = loginData.encode('ascii')
#By looking at the source of your Shib login form, find the URL the form action posts back to
#hard code this URL in the mock URL presented below.
#Make sure you include the URL, port number and path
response = opener.open("https://test-idp.server.example", bLoginData)
#See what you got.
print (response.read())
Ответ 7
Я столкнулся с аналогичной проблемой и с моей аутентификацией SAML на университетской странице.
Основная идея - использовать объект requests.session
для автоматической обработки большинства переадресаций и хранения файлов cookie. Однако было много переадресаций, использующих как javascript, так и это вызвало множество проблем с помощью простого запроса.
Я закончил использование fiddler, чтобы отслеживать каждый запрос, сделанный моим браузером на университетский сервер, чтобы заполнить перенаправления, которые я пропущенный. Это действительно облегчило процесс.
Мое решение далека от идеала, но, похоже, работает.