通过 Web 服务公开网站

Exposing a web site through web services

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

我想使用Selenium WebDriver之类的东西,所以我根据网络服务请求模拟了应用程序的网络点击。

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

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

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

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

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

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

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

我们做一些类似于代表用户访问网上银行的事情,抓取他的账户数据并获得信用评分。在大多数情况下,我们已经设法对移动应用程序进行逆向工程并嗅探流量以使用未记录的 API。在其他情况下,我们必须退回到网络抓取。

您可以抓取另外两种类型的应用程序:

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

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

根据你的解释,我了解到你属于后一种情况。

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

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

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

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

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

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

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

如果用户有效(用户登录凭据与服务器中的凭据匹配)则生成唯一令牌,通过与用户 ID 映射将令牌存储在服务器中, 在响应 header 中设置相同的标记或创建包含标记的 cookie。 通过这样做,我们可以避免通过仅在响应 header 或 cookie 中查找令牌来验证来自同一用户的以下请求的凭据。 如果服务被设计成chcek login every time the "Authorization" header 需要在每次发出请求时在请求中设置。

我认为使用 webdriver 的开销很大,但这取决于您真正想要实现的目标。根据您提供的信息,我宁愿使用 restTemplate 实现,将适当的 http 消息发送到现有的 webapp,用一个漂亮的 @service 层包装它,并在上面构建您的 web 服务(rest 或 soap)

身份验证是配置问题,您可以使用 @EnableOAuth2Sso 和您的 restTemplate bean 将其打包到微服务中,感谢 spring 启动,将处理下划线身份验证部分给你。

可能有点矫枉过正.....但是 RPA? http://windowsitpro.com/scripting/review-automation-anywhere-enterprise