【问题标题】:Search fourquare place using JavaScript WITHOUT exposing the client secret在不暴露客户端密码的情况下使用 JavaScript 搜索四方位
【发布时间】:2014-10-27 05:42:47
【问题描述】:

我正在阅读 Foursquare API 并试图找到如何将其用于地点搜索(作为 Google Places 的替代品)。但是我很惊讶它需要始终提供客户端密钥!。

我在浏览器中使用它,获得响应的唯一方法是在请求中提供客户端密码和客户端 ID。它是“客户端密码”,应该有另一种方法来做到这一点,而不使用客户端密码。 Google API 检查引荐网址和客户端 ID。 Foursquare 支持这样的东西吗?

我知道我可以在我的服务器中向foursquare 发出请求,并从我的JavaScript 客户端代码中调用它。但这将是非常难看的(IMO),因为用户必须等待双倍的响应时间user -> my-server -> foursquare-api 而不仅仅是user -> foursquare-api

我的 Web 应用程序中将使用它的页面:Where can I a great place in the city to see Christmas lights in Boston, MA?,尝试分享一个提示以找出答案(您不必真正发布它!)。

【问题讨论】:

  • 我现在正在做代理解决方案,它足够安全但由于user -> my-server -> foursquare-api而仍然很慢

标签: javascript api oauth-2.0 authentication foursquare


【解决方案1】:

这是我从一位开发人员那里学到的技巧。

它不是代理,但类似。它仍然会从您的 IP 地址(而不是服务器)发出请求,但签名发生在服务器上。它不会产生大量的网络流量。

基本上它只是一个签名端点。您在服务器上创建一个页面,该页面仅对请求进行签名,但实际上并不执行它。然后,您使用 Location: https://api.foursquare.com/... 标头将用户重定向到页面的签名版本。

请注意,所有签名都发生在服务器上,但实际请求是由客户端发出的。因为它们只在服务器上使用,所以不会暴露任何秘密。

【讨论】:

  • 我见过一种类似的技术,但使用 YQL 为您代理调用。您可以将密钥存储在 Yahoo 等的文件中。我相信您也可以通过 couchdb 找到一些不错的东西。
  • AFAIK Foursquare 不支持签名请求!所以无论如何您都必须公开客户端密码。要么在标头中的 JS 代码中,但另一个不太可能被注意到。
  • Foursquare 支持 OAuth。所以,是的,上述方法将起作用。
【解决方案2】:

很丑,是的。但我的两分钱:

如果您对安全性的需求远大于对速度的需求,那么请使用服务器端代理……这基本上是每个人都在做的事情,大多数代理都以某种方式伪装,有些是第 3 方服务,有些是小型独立的rails/express/etc 应用程序,有些只是您现有应用程序的端点,有些使用 google appengine,但不要自欺欺人,大多数人使用代理。

如果您对速度的需求大大超过了对安全性的需求:那么请采用“不安全”的方式来暴露您的密钥。只要您将不是来自foursquare 的用户敏感的数据与通过foursquare 访问的数据分离,这实际上并没有那么糟糕。你只是在分享一些可能是假的地理数据,一些可能是假的地点数据,而且,你明白了:这不是你用户的财务报表,而是一个名为 Foursquare 的大游戏。更糟糕的是,偶尔更改您的 API 密钥。

IMO,在这样的情况下,没有中间立场,您必须在头脑中平衡它,以使一个大大超过另一个(安全与速度)。我还没有看到两者都真正和诚实地同等重要并且没有什么可以权衡的情况。

【讨论】:

  • 提示:nodejs.org 让您可以使用服务器端 javascript 来执行此操作,并且非常适合这种代理,速度方面。
【解决方案3】:

代理方法确实帮助了我。我的应用程序在嵌入式码头上运行,我使用了 ProxyServelt 来解决这个问题:

    import java.net.URI;

    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.ws.rs.core.UriBuilder;

    import org.eclipse.jetty.client.HttpClient;
    import org.eclipse.jetty.client.api.Request;
    import org.eclipse.jetty.proxy.ProxyServlet;
    import org.eclipse.jetty.util.ssl.SslContextFactory;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    public class FoursquareProxyServlet extends ProxyServlet {
        public  static final String FOURSQUARE_API_PREFIX = "foursquare";

    private static final long serialVersionUID = 1L;
    private static final Logger LOG = LoggerFactory.getLogger(FoursquareProxyServlet.class);
    private static final String FOURSQUARE_API_VERSION = "20141026";

    private String apiURL;
    private String clientId;
    private String clientSecret;

    public void init() throws ServletException {
        super.init();

        ServletConfig config = getServletConfig();
        apiURL       = config.getInitParameter("foursquare.apiUrl");
        clientId     = config.getInitParameter("foursquare.clientId");
        clientSecret = config.getInitParameter("foursquare.clientSecret");
    }

    @Override
    protected void customizeProxyRequest(Request proxyRequest, HttpServletRequest request) {
        proxyRequest.getHeaders().remove("Host");
    }

    @Override
    protected URI rewriteURI(HttpServletRequest request) {
        URI uri = UriBuilder.fromUri(this.apiURL)
            .path(request.getRequestURI().replaceAll("/foursquare", ""))
            .replaceQuery(request.getQueryString().trim())
            .queryParam("client_id", this.clientId)
            .queryParam("client_secret", this.clientSecret)
            .queryParam("v", FOURSQUARE_API_VERSION)
            .build();

        return uri;
    }

    protected HttpClient newHttpClient() {
        SslContextFactory sslContextFactory = new SslContextFactory();
        HttpClient httpClient = new HttpClient(sslContextFactory);
        return httpClient;
    }
}

然后你只需要把它插入你的服务器:

protected ServletContextHandler createFoursquareProxy() {
    ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setContextPath("/"+FoursquareProxyServlet.FOURSQUARE_API_PREFIX+"/*");

    ServletHolder foursquareProxy = new ServletHolder("foursquare", new FoursquareProxyServlet());
    foursquareProxy.setInitParameter("foursquare.apiUrl", this.foursquareApiUrl);
    foursquareProxy.setInitParameter("foursquare.clientId", this.foursquareClientId);
    foursquareProxy.setInitParameter("foursquare.clientSecret", this.foursquareClientSecret);

    context.addServlet(foursquareProxy, "/*");
    return context;
}

在这种情况下,您的请求将如下所示:

GET http://{host}:{port}/foursquare/venues/search?&ll=40.7,-74%20&query=sushi

我相信你能用你的堆栈找出类似的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-14
    • 1970-01-01
    • 2020-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多