繁体   English   中英

通过网络服务公开网站

[英]Exposing a web site through web services

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

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

我想知道这是否是一个更好的解决方案或模式来做到这一点。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

身份验证是一个配置问题,您可以使用@EnableOAuth2Sso将其打包在微服务中,并且您的restTemplate bean 会为您处理下划线身份验证部分,这要归功于 spring boot。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM