【问题标题】:Authenticating on ADFS with Python script使用 Python 脚本在 ADFS 上进行身份验证
【发布时间】:2019-02-27 09:59:41
【问题描述】:

我需要解析被 ADFS 服务隐藏的站点。

并努力对其进行身份验证。

有什么选择吗?

我可以看到,后端应用程序或“系统用户”(使用 app_id、app_secret)的大多数解决方案。 就我而言,我不能使用它,只有登录名和密码。

问题示例: 在chrome 我打开www.example.com,它会将我重定向到https://login.microsoftonline.com/,然后使用登录名和密码表单重定向到https://federation-sts.example.com/adfs/ls/?blabla

以及如何使用python3 访问它?

【问题讨论】:

    标签: python parsing adfs


    【解决方案1】:

    ADFS 使用复杂的重定向和 CSRF 保护技术。因此,最好使用浏览器自动化工具来执行身份验证并在之后解析网页。我推荐带有 python 绑定的selenium toolkit。这是一个工作示例:

    from selenium import webdriver
    def MS_login(usrname, passwd):  # call this with username and password
        driver = webdriver.Edge()   # change to your browser (supporting Firefox, Chrome, ...)
        driver.delete_all_cookies() # clean up the prior login sessions
        driver.get('https://login.microsoftonline.com/') # change the url to your website
        time.sleep(5) # wait for redirection and rendering
    
        driver.find_element_by_xpath("//input[@name='loginfmt'").send_keys(usrname)
        driver.find_element_by_xpath("//input[@type='submit']").click()
        time.sleep(5)
    
        driver.find_element_by_xpath("//input[@name='passwd'").send_keys(passwd)
        driver.find_element_by_xpath("//input[@name='KMSI' and @type='checkbox'").click()
        driver.find_element_by_xpath("//input[@type='submit']").click()
        time.sleep(5)
    
        driver.find_element_by_xpath("//input[@type='submit']").click()
    
        # Successfully login
    
        # parse the site ...
    
        driver.close() # close the browser
        return driver
    

    此脚本调用 Microsoft Edge 打开网站。它将用户名和密码注入正确的 DOM 元素,然后让浏览器处理其余部分。已经在网页“https://login.microsoftonline.com”上进行了测试。您可能需要对其进行修改以适合您的网站。

    【讨论】:

    • 据我所知,selenium 将需要更多对主机的依赖。例如,我无法在 AWS Lambda 上运行它。
    • 令我惊讶的是,实际上您可以在 AWS Lambda 中运行 selenium 和无头 Chrome。谷歌搜索后,我发现了几篇教程文章[123]。这是您的目标环境吗?
    • 有道理!这样看起来更好。但是,我很惊讶只有会话没有解决方案......
    • @Psychozoic 有一个只有请求的解决方案,但它要求您了解所有端点并做 UI 正在做的任何请求准备(这可能不是微不足道的,比如将 CSRF 令牌添加到标题和诸如此类的东西)。使用浏览器自动化要简单得多。没有人会在 StackOverflow 上为您编写 CSRF 解决方法,因为这需要打开浏览器并解析他们的 JS 和请求标头,以弄清楚如何设置浏览器将为您执行的信息。
    • @julian,这是真的,我同意...我认为微软的东西已经有了解决方案。
    【解决方案2】:

    为了回答您的问题“如何使用 python”,我假设您希望在受 Azure AD 身份验证保护的页面上执行一些网络抓取操作。

    在这种情况下,您必须执行以下步骤。

    1. 对于这个脚本,我们只需要导入以下内容:

      导入请求 从 lxml 导入 html

    首先,我们要创建会话对象。该对象将允许我们在所有请求中保持登录会话。

    session_requests = requests.session()
    

    其次,我们想从网页中提取 csrf 令牌,这个令牌在登录时使用。对于这个示例,我们使用 lxml 和 xpath,我们可以使用正则表达式或任何其他可以提取此数据的方法。

    login_url = "https://bitbucket.org/account/signin/?next=/"
    result = session_requests.get(login_url)
    
    tree = html.fromstring(result.text)
    authenticity_token = list(set(tree.xpath("//input[@name='csrfmiddlewaretoken']/@value")))[0]
    

    接下来,我们要执行登录阶段。在这个阶段,我们向登录 url 发送一个 POST 请求。我们使用在上一步中创建的有效负载作为数据。我们还为请求使用了一个标头,并为相同的 url 添加了一个referer key。

    result = session_requests.post(
        login_url, 
        data = payload, 
        headers = dict(referer=login_url)
    )
    

    有效负载将是用户名和密码等的字典对象。

    payload = {
        "username": "<USER NAME>", 
        "password": "<PASSWORD>", 
        "csrfmiddlewaretoken": "<CSRF_TOKEN>"
    }
    

    注意:-这只是一个例子。

    第 2 步:

    抓取内容

    现在,我们能够成功登录,我们将执行实际的抓取

    url = 'https://bitbucket.org/dashboard/overview'
    result = session_requests.get(
        url, 
        headers = dict(referer = url)
    )
    

    也就是说,您需要从 Azure AD 获取请求详细信息有效负载,然后使用 login 方法创建会话对象,最后进行抓取。

    这是一个很好的安全网站网络抓取示例。

    希望对你有帮助。

    【讨论】:

    • 谢谢,但是...在 ADFS 的情况下,重定向到 https://login.microsoftonline.com/e0793d39-0939-496d-b129-198edd916feb/wsfed?blabla,其中 e0793d39-0939-496d-b129-198edd916feb 生成每个请求。接下来它再次重定向到 https://federation-sts.example.com/adfs/ls/blabla... 是否可以询问需要的页面,并获得最终页面,在哪里询问登录名和密码?或者我需要知道那个网址?
    • 而且,正如我所见,有很多字段,看起来像 token... 但我不能确定需要什么。有没有解决方案,抓住所有并将其全部传递给请求的资源?
    • 无论如何,您都可以触发首次登录页面并获得最终的登录窗口 URL,这样您就可以获取该 URL,以防万一由于设置更改而每次都更改。
    • 通常对于任何 Azure AD 身份验证,您需要在请求中发送一些标头,它们是客户端 _id、redirect_uri、response_type、范围,最后是看起来像 login.microsoftonline.com/common/oauth2/authorize 的 url。
    猜你喜欢
    • 2013-08-31
    • 2016-09-30
    • 2022-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    • 1970-01-01
    相关资源
    最近更新 更多