python login saml saml-2.0 shibboleth

Iniciar sesión en el servidor autenticado SAML/Shibboleth usando python



login saml-2.0 (8)

Estoy intentando iniciar sesión en el servidor de mi universidad a través de python, pero no estoy completamente seguro de cómo generar los POST HTTP adecuados, crear las claves y los certificados, y otras partes del proceso con las que no estoy familiarizado y que debo conocer. cumplir con la especificación SAML. Puedo iniciar sesión con mi navegador, pero me gustaría poder iniciar sesión y acceder a otros contenidos dentro del servidor usando Python.

Para referencia, aquí está el sitio.

He intentado iniciar sesión utilizando mecanizar (seleccionando el formulario, rellenando los campos, haciendo clic en el botón del botón de enviar a través de mecanizar. Anotación. Enviar (), etc.) sin éxito; El sitio de inicio de sesión se escupe cada vez.

En este punto, estoy abierto a implementar una solución en el idioma que sea más adecuado para la tarea. Básicamente, quiero iniciar sesión programáticamente en el servidor autenticado SAML.


Ampliando la respuesta de Stéphane Bruckert más arriba, una vez que haya usado Selenium para obtener las cookies de autenticación, aún puede cambiar a las solicitudes si desea:

import requests cook = {i[''name'']: i[''value''] for i in driver.get_cookies()} driver.quit() r = requests.get("https://protected.ac.uk", cookies=cook)


Aunque ya respondí, espero que esto ayude a alguien. Tenía la tarea de descargar archivos de un sitio web de SAML y recibí ayuda de la respuesta de Stéphane Bruckert.

Si se utiliza sin cabeza, el tiempo de espera deberá especificarse en los intervalos de redirección requeridos para el inicio de sesión. Una vez que el navegador inició sesión, utilicé las cookies y las utilicé con el módulo de solicitudes para descargar el archivo. Obtuve ayuda de esto .

Así es como se ve mi código

from selenium import webdriver from selenium.webdriver.chrome.options import Options #imports things_to_download= [a,b,c,d,e,f] #The values changing in the url options = Options() options.headless = False driver = webdriver.Chrome(''D:/chromedriver.exe'', options=options) driver.get(''https://website.to.downloadfrom.com/'') driver.find_element_by_id(''username'').send_keys("Your_username") #the ID would be different for different website/forms driver.find_element_by_id(''password'').send_keys("Your_password") driver.find_element_by_id(''logOnForm'').submit() session = requests.Session() cookies = driver.get_cookies() for things in things_to_download: for cookie in cookies: session.cookies.set(cookie[''name''], cookie[''value'']) response = session.get(''https://website.to.downloadfrom.com/bla/blabla/'' + str(things_to_download)) with open(''Downloaded_stuff/''+str(things_to_download)+''.pdf'', ''wb'') as f: f.write(response.content) # saving the file driver.close()


Básicamente, lo que debe comprender es el flujo de trabajo detrás de un proceso de autenticación SAML. Desafortunadamente, no hay un PDF por ahí que parezca realmente proporcionar una buena ayuda para descubrir qué tipo de cosas hace el navegador cuando accede a un sitio web protegido por SAML.

Tal vez debería echar un vistazo a algo como esto: http://www.docstoc.com/docs/33849977/Workflow-to-Use-Shibboleth-Authentication-to-Sign y obviamente a esto: http://en.wikipedia.org/wiki/Security_Assertion_Markup_Language . En particular, enfoca tu atención a este esquema:

Lo que hice cuando intentaba entender la forma de trabajar de SAML, ya que la documentación era muy deficiente, fue anotar (sí, escribiendo - en el papel) todos los pasos que el navegador estaba realizando desde el primer hasta el último. Utilicé Opera, configurándolo para no permitir redirecciones automáticas (300, 301, código de respuesta 302, etc.), y tampoco habilito Javascript. Luego anoté todas las cookies que el servidor me estaba enviando, qué estaba haciendo qué y por qué motivo.

Tal vez fue demasiado esfuerzo, pero de esta manera pude escribir una biblioteca, en Java, que es adecuada para el trabajo, y también increíblemente rápida y eficiente. Tal vez algún día lo publique públicamente ...

Lo que debe entender es que, en un inicio de sesión SAML, hay dos actores jugando: el IDP (proveedor de identidad) y el SP (proveedor de servicios).

A. PRIMER PASO: el agente de usuario solicita el recurso al SP

Estoy seguro de que llegó al enlace al que hace referencia en su pregunta desde otra página haciendo clic en algo como "Acceso al sitio web protegido". Si le presta más atención, notará que el enlace que siguió no es en el que se muestra el formulario de autenticación. Esto se debe a que hacer clic en el enlace del IDP al SP es un paso para el SAML. El primer paso, en realidad. Le permite al IDP definir quién es usted y por qué está intentando acceder a su recurso. Básicamente, lo que deberá hacer es solicitar el enlace que siguió para acceder al formulario web y obtener las cookies que configurará. Lo que no verá es una cadena de solicitud SAML, codificada en el redireccionamiento 302 que encontrará detrás del enlace, que se envía al IDP que realiza la conexión.

Creo que es la razón por la que no puedes mecanizar todo el proceso. Simplemente se conectó al formulario, ¡sin que se haya identificado su identidad!

B. SEGUNDO PASO: llenando el formulario y enviándolo.

Este es fácil. ¡Por favor tenga cuidado! Las cookies que ahora están configuradas no son las mismas que las anteriores. Ahora te estás conectando a un sitio web completamente diferente. Esa es la razón por la que se usa SAML: un sitio web diferente, las mismas credenciales . Por lo tanto, es posible que desee almacenar estas cookies de autenticación, proporcionadas por un inicio de sesión exitoso, a una variable diferente. El IDP ahora le enviará una respuesta (después de SAMLRequest): SAMLResponse. Debe detectarlo obteniendo el código fuente de la página web a la que finaliza el inicio de sesión. De hecho, esta página es un formulario grande que contiene la respuesta, con algo de código en JS que se subtitula automáticamente cuando se carga la página. Tienes que obtener el código fuente de la página, analizarlo, deshacerte de todas las cosas no útiles de HTML y obtener el SAMLResponse (encriptado).

C. TERCER PASO: devolver la respuesta al SP

Ahora estás listo para terminar el procedimiento. Debe enviar (a través de POST, ya que está emulando un formulario) el SAMLResponse obtenido en el paso anterior, al SP. De esta manera, proporcionará las cookies necesarias para acceder a las cosas protegidas a las que desea acceder.

Aaaaand, has terminado!

Una vez más, creo que lo más preciado que tendrá que hacer es usar Opera y analizar TODAS las redirecciones que hace SAML. Luego, replicalas en tu código. No es tan difícil, solo tenga en cuenta que el IDP es completamente diferente al SP.


Escribí un sencillo script de Python capaz de iniciar sesión en una página Shibbolized.

Primero, usé los encabezados HTTP en vivo en Firefox para ver los redireccionamientos de la página Shibbolized en particular a la que me dirigía

Luego escribí un script simple usando urllib.request (en Python 3.4, pero el urllib2 en Python 2.x parece tener la misma funcionalidad). Descubrí que el seguimiento de redirección predeterminado de urllib.request funcionó para mis propósitos, sin embargo, me pareció bueno subclasificar urllib.request.HTTPRedirectHandler y en esta subclase (clase ShibRedirectHandler ) agregar un controlador para todos los eventos http_error_302.

En esta subclase acabo de imprimir los valores de los parámetros (para propósitos de depuración); tenga en cuenta que para utilizar la siguiente redirección predeterminada, debe finalizar el manejador con el return HTTPRedirectHandler.http_error_302(self, args...) (es decir, una llamada al manejador http_errror_302 de la clase base).

El componente más importante para hacer que urllib funcione con la Autenticación Shibbolized es crear OpenerDirector que tenga el manejo de Cookie agregado. Construye el OpenerDirector con lo siguiente:

cookieprocessor = urllib.request.HTTPCookieProcessor() opener = urllib.request.build_opener(ShibRedirectHandler, cookieprocessor) response = opener.open("https://shib.page.org")

Aquí hay un script completo que puede comenzar (deberá cambiar algunas de las URL simuladas que proporcioné y también ingresar un nombre de usuario y contraseña válidos). Esto utiliza clases de Python 3; para hacer que esto funcione en Python2, reemplace urllib.request con urllib2 y urlib.parse con 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())


Mechanize puede hacer el trabajo también, excepto que no maneja Javascript. La autentificación funcionó correctamente, pero una vez en la página de inicio, no pude cargar dicho enlace:

<a href="#" id="formMenu:linknotes1" onclick="return oamSubmitForm(''formMenu'',''formMenu:linknotes1'');">

En caso de que necesite Javascript, use Selenium mejor con PhantomJS . De lo contrario, espero que encuentres inspiración de este guión:

#!/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)


Selenium con el kit web PhantomJS sin cabeza será su mejor opción para iniciar sesión en Shibboleth, ya que maneja cookies e incluso Javascript para usted.

Instalación:

$ 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

Nota:

  • durante el desarrollo, use Firefox para obtener una vista previa de lo que está haciendo driver = webdriver.Firefox()
  • este script se proporciona tal como está y con los enlaces correspondientes, por lo que puede comparar cada línea de código con el código fuente real de las páginas (hasta el inicio de sesión, al menos).

También tuve un problema similar con la autenticación SAML de mi página universitaria.

La idea básica es utilizar un objeto requests.session para manejar automáticamente la mayoría de los redireccionamientos http y el almacenamiento de cookies. Sin embargo, hubo muchos redireccionamientos que usan tanto javascript también, y esto causó múltiples problemas al usar la solución de solicitudes simples.

Terminé usando fiddler para realizar un seguimiento de todas las solicitudes que mi navegador realizó al servidor de la universidad para completar los redireccionamientos que perdí. Realmente hizo el proceso más fácil.

Mi solución está lejos de ser ideal, pero parece funcionar.


here puede encontrar una descripción más detallada del proceso de autenticación de Shibboleth.