Подтвердить что ты не робот

Вход в сервер аутентификации SAML/Shibboleth с использованием python

Я пытаюсь войти в свой университетский сервер через python, но я совершенно не уверен, как идти о создании соответствующих HTTP POST, создавая ключи и сертификаты, а также другие части процесса, которые могут быть незнакомы с этим должны соответствовать спецификации SAML. Я могу войти в мой браузер просто отлично, но я хотел бы иметь возможность входа и доступа к другому содержимому на сервере с помощью python.

Для справки вот сайт

Я пробовал войти в систему, используя механизацию (выбор формы, заполнение полей, нажатие кнопки кнопки отправки через mechanize.Broswer.submit() и т.д.) безрезультатно; сайт входа в систему каждый раз отбрасывается.

В этот момент я открыт для реализации решения в зависимости от того, какой язык наиболее подходит для этой задачи. В принципе, я хочу программно войти на сервер, прошедший проверку на SAML.

4b9b3361

Ответ 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, чтобы отслеживать каждый запрос, сделанный моим браузером на университетский сервер, чтобы заполнить перенаправления, которые я пропущенный. Это действительно облегчило процесс.

Мое решение далека от идеала, но, похоже, работает.