2

在服务器上,有什么方法可以区分内部和外部 REST API 请求?

为什么?

我想区分这两个来源的原因是,根据受访者给出的建议,我可能想要返回不同的数据集,具体取决于谁试图提出请求。

概括

我对内部的定义可能不正确。在这种情况下,“内部”是指来自与处理请求的页面相同的域的 XHTTP 请求发出的请求。

外部调用可能是用户从另一个域创建 Curl 请求。

例如:

http.service.ts

内部角度 6 请求


fetchLogin(formData: any): Observable<any> {
    let req = null;
    let headers = null;
    headers = {
      reportProgress: false,
      headers: new HttpHeaders({
        'email': formData['email'],
        'password': formData['password']
      })
    };
    req = new HttpRequest('POST', this.restApiUrl + this.restApiUrlEndpoint + '/oauth/', '', headers);
    return this.http.request(req)
    .map( (data) => {
      return 'body' in data ? data['body'] : null;
    })
    .pipe(
      catchError(this.handleError)
    );
  }

模板.cfm

外部冷融合请求


<cfset httpUrl = request.restApiUrl & request.restApiUrlEndpoint & "/oauth/">

<cfhttp url="#httpUrl#" method="post" result="result" timeout="30">
  <cfhttpparam type="header" name="email" value="foo@bar.com" />
  <cfhttpparam type="header" name="password" value="foo" />
</cfhttp>

请理解,我已经简化了这两个代码片段以保持清晰。

当请求到达服务器时,我如何知道哪个请求是通过 XHTTP 来的,哪个是通过 CFHTTP [Curl] 发送的?

我正在使用 Taffy.io REST API 框架,所以这是一个简化的方法,在“资源”CFC 中,我可能会使用它来处理请求:

资源/oauthMember.cfc

<cfcomponent extends="taffy.core.resource" taffy_uri="/oauth">

<cffunction name="post">
  <cfset var local = StructNew()>
  <cfset local.data['email'] = "">
  <cfset local.data['password'] = "">
  <cfset local.requestBody = getHttpRequestData().headers>
  <cftry>
    <cfset local.data['email'] = Trim(local.requestBody['email'])>
    <cfset local.data['password'] = Trim(local.requestBody['password'])>
    <cfcatch>
    </cfcatch>
  </cftry>
  ...processing code
  <cfreturn representationOf(local.data) />
</cffunction>

</cfcomponent>

向其中一个调用添加额外的标头是不可行的,因为这很容易被欺骗。

有任何想法吗?

环境

Windows 2008R2 Lucee 4.5 IIS7+

4

1 回答 1

3

简而言之,您不能相信公共 REST API 数据中的任何即将到来的请求。请求内容/标题中的任何内容都可以通过 curl 或自定义程序构造。如果您的 Web 服务器进行了相应配置并且可以从套接字本身直接访问源连接地址,那么您可能对套接字源 IP 地址有一定的信任。现在这种情况很少见,因为通常 Web 服务器现在位于负载均衡器、带有 NAT 隧道的防火墙等后面。但即使在这种情况下,源 IP 地址也可能仅用于某种​​白名单。此外,今天具有这种访问权限的服务器明天可能会失去它,因为您的应用程序可能需要负载均衡器来扩展。另请注意,用户可能在源路径上有 HTTP 代理。因此,使用源 IP 作为 API 标准看起来是一种不好的做法。

好的做法是创建对调用者不变的公共 API。API 调用应集中在提供的 REST 请求正文和标头上,以检查其有效性、可接受性和安全性。实际上,许多 API 调用应该按“登录” -> sessionToken -> “使用 sessionToken 的 API 调用” -> “使用 sessionToken 注销”(令牌无效)的顺序完成。在这种情况下,重要数据(用户 ID、角色、安全上下文等)以某种方式存储在连接到 sessionToken 的服务器上。注意:许多 API 架构师不建议将 sessionToken 存储在 cookie 中,因为它可能会简化 CSRF 攻击(如果没有提供其他对策)。

您和可能许多其他人想要的是拥有“私有”API 来实现您的网站功能本身和“公共”API 给您的客户。那是一个有点不同的故事。

您记录、发布(至少对客户)的公共 API,承诺在​​很长一段时间内保持不变。

您可以随时更改私有 API,并且可以以您觉得舒适的方式对其进行设计。但是,如果您的网站是实时的,任何人仍然可以扫描自己的流量并使用 curl(或类似的东西)构建类似的请求。但是,您可能会采取一些技巧让滥用者的生活更加艰难,例如发布某种 JavaScript 计算的页面令牌、使用短期请求链等,但这并不能完全消除威胁。因此,如果请求的所有数据都可以从合法用户的页面和流量中获取,API 就无法中继“没有人可以构造这样的请求”。

简历:最好有客户的公共 API 和站点本身的私有 API,不要混合它们。

于 2019-02-02T12:39:09.587 回答