【问题标题】:Exposing a web site through web services通过 Web 服务公开网站
【发布时间】:2017-11-28 19:27:52
【问题描述】:

我知道我在问什么有点奇怪。有一个 Web 应用程序(我们无法访问它的源代码),我们希望将它的一些功能公开为 Web 服务。

我正在考虑使用 Selenium WebDriver 之类的东西,所以我根据 Web 服务请求模拟了应用程序上的 Web 点击。

我想知道这是否是更好的解决方案或模式。

我将提到该应用程序是使用 Java、Spring MVC(它不是 SPA)和 Spring Security 编写的。并且有一个提供 SSO 的 CAS 服务器。

【问题讨论】:

  • JSoup 可能是一种选择。只是为了发送请求和解析响应
  • 我试过了,但我无法使用它登录应用程序,它使用 CAS 和 Spring Security 进行身份验证。
  • 您搜索过网络吗?我很容易找到this。如果这不能解决您的问题,您能否说明有什么不同?
  • @MikeJRamsey56 正如我所说,我知道 Selenium,但问题是生成的 Web 服务不会那么高效。考虑一下我将模拟登录系统,导航到正确的菜单,然后提交正确的数据。

标签: java spring selenium automation java-service-wrapper


【解决方案1】:

我们会执行类似的操作,例如代表用户访问网上银行、抓取他的帐户数据并获得信用评分。在大多数情况下,我们已经设法对移动应用程序进行逆向工程并嗅探流量以使用未记录的 API。在其他情况下,我们不得不退回到网络抓取。

您可以抓取其他两种类型的应用程序:

  • 对于任何用户而言,数据基本上都是相同的,例如亚马逊中的产品列表
  • 数据特定于每个用户,就像在银行应用程序中一样。

在第一种情况下,您可以让您的抓取工具运行并填充本地数据库,并使用您的本地数据来提供 Web 服务。在后一种情况下,您不能这样做,您需要根据用户的请求抓取网站。

我从您的解释中了解到,您属于后一种情况。

当网络抓取时,您会发现非常困难的网络应用:

  • 有些可能会要求您将先前请求中的数据发送到下一个请求
  • 其他人使用 JavaScript 在客户端呈现大部分数据

如果这两种情况中的任何一种是您的情况,Selenium 将使您的实现更容易,但性能不佳。

在不使用 selenium 的情况下实施第一个将需要您进行大量尝试错误以使事情正常运行,因为您将模拟请求并且您需要知道客户端期望的数据。而如果您使用 selenium,您将执行与浏览器相同的交互,从而发送预期的数据。 实现第二种情况需要你的爬虫支持 JavaScript。 AFAIK 的最佳支持由 selenium 提供。 HtmlUnit 声称提供公平的支持,我认为 JSoup 不提供对 JavaScript 的支持。

最后,如果您的解决方案花费了太多时间,您可以通过类似于 Webhooks 或Resthooks 的通知机制为您的 Web 服务提供解决方案:

  1. 您的 Web 服务的客户端会请求数据,并提供一个 URI,他们希望在结果准备好后收到通知。
  2. 您的服务会立即响应请求的 ID,并开始在后台抓取必要的信息。
  3. 如果您使用瘦负载模型,则在完成抓取后,您会将响应存储在数据存储中,并带有标识原始请求的 ID。此响应将作为资源公开。
  4. 您将在客户端提供的 URI 上执行 HTTPPOST。在请求正文中,您将添加响应资源的 URI。
  5. 客户端现在可以GET 响应资源,因为请求和响应具有相同的 id,客户端可以关联两者。

【讨论】:

  • 感谢您的回复,不幸的是,该应用程序使用 Spring Web Flow(尽管它的大多数用例都不是基于流的!),单击大多数链接会创建一个具有新流 ID 的新流。
  • 为什么这是一个问题,以及提供了哪些可能的解决方案?你能详细说明一下吗?
  • 那么应用程序是在一个私有网络上,并且应该通过一些网络服务暴露给互联网。在专用网络上不允许我使用一些基于互联网云的解决方案。我将在该专用网络上托管所有机器人(或任何东西)。我会尝试使用 HtmlUnit 来确定应用程序 JavaScript 是否可以。
  • 您最后的解决方案看起来不错。我现在就试一试。
  • 可能是沟通不畅,但我评论的所有可能性都不包括 SaaS 或云服务。 Resthooks 只是一个关于如何在 rest 服务中进行异步通信的提案、规范。这不是一个解决方案。
【解决方案2】:

【讨论】:

    【解决方案3】:

    我认为使用webdriver 会产生很多开销,但这取决于您真正想要实现的目标。根据您提供的信息,我宁愿使用 restTemplate 实现向现有的 web 应用程序发送适当的 http 消息,用漂亮的 @service 层包装它,并在其上构建您的 Web 服务(休息或肥皂)。

    身份验证是一个配置问题,您可以使用@EnableOAuth2Sso 和您的restTemplate bean 将其打包在一个微服务中,感谢spring boot,它将为您处理下划线的身份验证部分。

    【讨论】:

      【解决方案4】:

      Selenium 不是使用 Web 服务的最佳方式。 Selenium 最好是一种自动化工具,主要用于测试应用程序。 假设服务已经开发完毕,我们需要做的第一件事是验证用户请求。 这可以通过添加一个 HttpHeader 来完成,键为“授权”,值为“基本”+ Base64Encode(username+":"+password)

      如果用户有效(用户登录凭据与服务器中的凭据匹配)则生成唯一令牌,通过与用户 ID 和映射的映射将令牌存储在服务器中 在响应标头中设置相同的令牌或创建包含令牌的 cookie。 通过这样做,我们可以避免验证来自同一用户的以下请求的凭据,只需在响应标头或 cookie 中查找令牌。 如果服务设计为每次发出请求时都需要在请求中设置“授权”标头时检查登录。

      【讨论】:

      • 正如我提到的,我需要一个自动化工具,因为遗留系统不提供 Web 服务,它是一个现有的 Web 应用程序。我想将它的一些功能公开为 Web 服务。
      • Amir Pashazadeh,我了解您的问题。我认为唯一的解决方案是通过访问源代码来开发 Web 服务。 Selenium 可能是合适的选择,因为该工具的用途不支持您的需求。
      【解决方案5】:

      有多种实现方式。在我看来,Selenium/PhantomJS 并不是最好的选择,因为如果 web 设计得当,你可以只使用提供的 HTML 甚至一些 API 与它交互,而不需要所有的 CSS,并执行 javascript 异步请求。由于您的页面不是 SPA,因此很可能已经以 GET/POST 请求的形式存在“API”,您可能很幸运没有 CSRF 保护。

      首先,您需要解决针对 CAS 的身份验证问题。 oAuth 中有多种类型的身份验证,但您应该获得一个 API 令牌,使您能够访问应用程序。这个令牌应该以 HTTP Header 或 Cookie 的形式添加到每个请求中。理想情况下,此令牌不应过期,否则您需要在应用中实现重新身份验证逻辑。

      身份验证部分解决后,您需要非常耐心,使用首选网络浏览器的网络检查器打开目标网站,然后转到“网络”面板并执行您希望以编程方式运行的操作。在那里,您会找到包含所有标头和内容以及响应的请求。 这就是您需要编码的内容。有很多库可以在 Java 中实现这一点。如果您需要解析 HTML,可以查看 Jsop,但要运行普通的 GET/POST 请求,请使用 RestTemplate(在 Spring 中)或 JAX-RS/Jersey 2 Client

      如果查询结果在一段时间内保持不变,您可能会考虑实施缓存层来提高性能,或者您可以假设在 5 分钟内,对同一查询的响应将相同。

      您可以使用自己喜欢的语言/框架创建应用。我建议从SpringBoot + MVC + DevTools 开始。如果您需要解析一些 HTML,那将包含您需要的所有内容 + Jsoup。稍后您可以根据需要添加缓存提供程序。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-12
        • 2011-02-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-22
        • 1970-01-01
        • 2011-05-16
        相关资源
        最近更新 更多