我正在阅读Foursquare API,并试图找到如何将其用于地点搜索(替代Google地方信息)。但是我很惊讶它需要始终提供客户端密钥!。
我在浏览器中使用它,获得响应的唯一方法是在请求中提供客户端密钥和客户端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?,尝试共享提示以便找出(您不必真正发布它!)。
答案 0 :(得分:2)
这是我从其他开发者那里学到的一个技巧。
它不是代理,但类似。它仍然会从您的IP地址(而不是服务器)发出请求,但是在服务器上进行签名。它不会产生大量的网络流量。
基本上它只是一个签名端点。您在服务器上创建一个页面,该页面仅签署请求但实际上并未执行该页面。然后,使用Location: https://api.foursquare.com/...
标头将用户重定向到已签名的页面版本。
请注意,所有签名都在服务器上进行,但实际请求是由客户端进行的。没有秘密暴露,因为它们只在服务器上使用。
答案 1 :(得分:1)
很难看,是的。但我的两分钱:
如果您对安全性的需求大大超过您对速度的需求,那么使用服务器端代理......这基本上是每个人都做的事情,大多数代理都以某种方式伪装,有些是第三方服务,有些是非常小的独立服务rails / express / etc应用程序,有些只是现有应用程序的端点,有些使用google appengine,但不要自欺欺人,大多数人都使用代理。
如果您对速度的需求大大超过您对安全性的需求:那么采用“不安全”的方式来暴露您的密钥。当你从foursquare访问的数据中分离出来自foursquare的用户敏感的数据时,它并没有那么糟糕。你只是分享了一些可能虚假的地理数据,一些可能是虚假的地方数据,好吧,你得到的图片:它不是你用户的财务报表,它是一款名为Foursquare的大型游戏。更糟糕的是,偶尔更改您的API密钥。
IMO,在这样的情况下,没有中间立场,你必须在头脑中保持平衡,以便一个人大大超过另一个人(安全性与速度)。我还没有看到这样一种情况,即两者都是真实而诚实地同等重要,没有任何东西可以被交易。答案 2 :(得分:0)
代理方法对我有帮助。我的应用程序在嵌入式jetty上运行,我使用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
我确定你能够找到与你的筹码类似的东西。