我试图通过Python登录我的大学的服务器,但我完全不知道应该如何去生成相应的HTTP的POST,创建密钥和证书,以及工艺的其它部分与所需要的可能是我不熟悉的遵守SAML规范。 我可以用我的浏览器登录就好了,但我希望能够登录并访问使用python服务器内的其他内容。
作为参考, 在这里是网站
我已经试过登录通过使用机械化(选择的形式,填充字段,点击经由mechanize.Broswer.submit()等提交按钮控制)无济于事; 登录的网站获得每次吐回。
在这一点上,我愿意实现解决方案在任何一个语言是最适合的任务。 基本上,我想以编程方式登录到SAML身份验证服务器。
Answer 1:
基本上你要明白的是后面的SAML认证过程的工作流程。 不幸的是,没有PDF在那里,这似乎确实提供找出什么样的东西访问到SAML保护的网站时,浏览器做了很好的帮助。
也许你应该看看到这样的事情: http://www.docstoc.com/docs/33849977/Workflow-to-Use-Shibboleth-Authentication-to-Sign显然这样: HTTP://en.wikipedia .ORG /维基/ Security_Assertion_Markup_Language 。 特别是,你的注意力集中到这个方案:
我所做的,当我试图了解工作的SAML方式,因为文件是如此之差,被写下来(是写-在纸张上)中的所有浏览器是从第一个到最后一个做的步骤。 我用歌剧,以便不允许自动重定向设置它(300,301,302响应代码,等等),并且还没有启用JavaScript。 于是我写下所有的服务器将派遣我的饼干,是什么在做什么,为了什么原因。
也许是太多的精力,但这样我可以写一个图书馆,在Java中,这是适合这份工作,incredibily快速和高效了。 也许有一天,我会释放它公开...
你应该明白的是,在SAML登录,有两个演员扮演:在IDP(身份提供商)和SP(服务提供商)。
A.第一步:用户代理请求资源的SP
我敢肯定,你达到了你在你的问题,从另一个页面点击,以类似“访问受保护的网站”引用链接。 如果你做一些更多的关注,你会发现,你跟着链接是不是在其中显示的认证形式之一。 这是因为从IDP向SP链接的点击是对SAML的一步 。 第一步骤中,actally。 它允许IDP来定义你是谁,为什么你试图访问其资源。 所以,基本上你需要做的就是让你遵循以达到Web表单链接的请求,并得到它会设置的cookie什么。 什么,你不会看到的是一个SAMLRequest字符串,编码到302重定向,你会发现链接,发送给IDP进行连接后面。
我认为,这就是为什么你不能机械化全过程的原因。 您只需连接形式,没有进行任何身份识别!
B.第二步:填写表格,并提交其
这一个是容易的。 请注意! 是现在设置的Cookie是不一样上面的饼干。 现在你连接到一个完全不同的网站。 这就是为什么使用SAML的原因: 不同的网站,相同的凭证 。 所以,你可能要存储这些身份验证Cookie,通过登录成功提供,在不同的变量。 该IDP现在会回送你一个响应(在SAMLRequest后):在SAMLResponse。 你要检测它让到登录结束网页的源代码。 事实上,这个页面包含响应,在JS一些代码,自动subits它,页面加载时,一个大单。 你必须得到该页面的源代码,分析它,摆脱所有的HTML无用的东西,得到SAMLResponse(加密)。
C.第三步:发送回SP的响应
现在,您可以结束程序。 你必须发送(通过POST,因为你模仿一种形式)的SAMLResponse在上一步了,到SP。 通过这种方式,它会提供访问您要访问受保护的东西所需要的饼干。
Aaaaand,大功告成!
同样,我认为你必须做的最宝贵的东西是使用Opera和分析所有重定向SAML一样。 然后,复制他们在你的代码。 这并不难,只要记住的是,IDP是比SP完全不同。
Answer 2:
硒与无头PhantomJS的webkit将登录到Shibboleth的你最好的选择,因为它处理饼干,甚至的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()
- 这个脚本是原样提供,并与相应的链接,这样你可以比较的每一行代码与页面的实际的源代码(直到登录至少)。
Answer 3:
扩展从斯特凡Bruckert答案上面,一旦你已经使用硒得到权威性的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)
Answer 4:
你可以找到这里的Shibboleth的认证过程的更详细的说明。
Answer 5:
我写了能够登录到Shibbolized页面的一个简单的Python脚本。
首先,我用活HTTP头在Firefox中观看特定Shibbolized页面我针对重定向。
然后我写了使用一个简单的脚本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认证工作是创建OpenerDirector
添加了这个cookie处理。 您打造OpenerDirector
有以下几点:
cookieprocessor = urllib.request.HTTPCookieProcessor()
opener = urllib.request.build_opener(ShibRedirectHandler, cookieprocessor)
response = opener.open("https://shib.page.org")
这里是一个可以让你开始(你需要改变我提供了一些模拟的URL,并输入有效的用户名和密码)的完整剧本。 此使用Python 3类; 使这项工作在Python2用的urllib2和urlib.parse与替换里urlparse urllib.request里:
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())
Answer 6:
机械化所能做的工作也只是它不处理JavaScript。 身份认证成功的工作,但一旦在网页上,我无法加载这样的链接:
<a href="#" id="formMenu:linknotes1"
onclick="return oamSubmitForm('formMenu','formMenu:linknotes1');">
如果你需要使用Javascript,更好地利用硒与PhantomJS 。 否则,我希望你能找到这个剧本的灵感:
#!/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)
Answer 7:
我遇到类似的问题,我的大学网页SAML认证为好。
基座想法是使用一个requests.session
对象自动处理大部分HTTP重定向和饼干存储的。 然而,有许多重定向同时使用JavaScript的为好,这引起了使用简单的请求解决多个问题。
最后我用小提琴手跟踪每个请求我的浏览器到了大学服务器进行填补我已经错过了重定向。 这真的使这个过程更容易。
我的解决方案是远远不够理想,但似乎工作。
Answer 8:
虽然已经回答了,希望这可以帮助someone.I不得不从SAML网站下载文件的任务,并得到了斯特凡Bruckert的回答帮助。
如果无头被使用,则等待时间都需要在重定向为登录所需的时间间隔中指定。 一旦浏览器登录我使用的cookie,并请求模块用它来下载文件- 从该得到帮助 。
这是我的代码看起来喜欢 -
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()
文章来源: Logging into SAML/Shibboleth authenticated server using python