Node.js 确保我的API只与我的前端一起工作

Node.js 确保我的API只与我的前端一起工作,node.js,api,authentication,reactjs,tokenize,Node.js,Api,Authentication,Reactjs,Tokenize,我正在构建一个node/express后端。我想创建一个只与我的reactjs前端(私有API)一起工作的API 想象一下,如果这是一个电子商务网站,我的用户将浏览产品,然后选择购买什么,在订购时,他们可能登录,也可能不登录 确保我的API只与我的reactjs前端一起工作的最佳实践是什么 当用户决定登录或保留为来宾时会发生什么情况?应用-服务器指定允许请求您的API的域 它是如何工作的 客户端向服务器发送特殊的“飞行前”请求(选项方法),询问域请求是否来自允许的域。它还询问请求方法是否正常(您

我正在构建一个node/express后端。我想创建一个只与我的reactjs前端(私有API)一起工作的API

想象一下,如果这是一个电子商务网站,我的用户将浏览产品,然后选择购买什么,在订购时,他们可能登录,也可能不登录

确保我的API只与我的reactjs前端一起工作的最佳实践是什么

当用户决定登录或保留为来宾时会发生什么情况?

应用-服务器指定允许请求您的API的域

它是如何工作的

  • 客户端向服务器发送特殊的“飞行前”请求(选项方法),询问域请求是否来自允许的域。它还询问请求方法是否正常(您可以允许GET,但拒绝POST,…)
  • 服务器决定是允许还是拒绝请求。它用“OK”响应并设置特殊的头,告诉您允许哪些域/请求方法
  • 若允许客户端查询您的API,它将执行预期的请求,或者退出 尊重COR(浏览器)的客户端将能够(或者如果被拒绝将不会)连接。如果客户端忽略CORS(REST客户端、CLI工具等),则无论发生什么情况,它都将能够连接


    尽管如此,要求签名请求(授权)

    因此,这可能是一个稍微冗长的回答——但您已经发布了一个相当有趣和重要的问题

    作为一个花了我大部分时间用Node和Python编写安全库来处理这类事情的人,我想我应该跳到这里来

    要用于保护React应用程序和后端API的协议是OAuth2密码授予流。理论上它的工作方式很简单

    在React应用程序上,您可以收集用户的用户名/密码(如果您是这样构造应用程序的,也可以是电子邮件/密码)

    然后向后端API发送POST请求,如下所示:

    POST api.myapp.com/oauth/token
    
    grant_type=password&username=USERNAME&password=PASSWORD
    
    在发布到服务器时,请确保使用
    应用程序/x-www-form-urlencoded
    内容类型

    然后,您的服务器将接收该请求,通过OAuth2库运行它,并生成两个令牌:以及访问和刷新令牌

    一旦在服务器端API上生成了令牌,就将这些令牌存储在cookie中,然后由用户的浏览器存储

    从这一点开始:一切都应该是自动的。当React服务器向后端发出API请求时,浏览器将通过包含这两个令牌的cookie自动识别用户

    您需要在服务器端使用OAuth2库,因为这将处理以下事项:

    • 生成令牌
    • 当刷新令牌过期时,将其交换为新的访问令牌
    • 基于令牌识别用户
    • 如果代币被泄露,则撤销代币,等等
    还有很多,但这是一个基本的,高层次的想法

    正如您所注意到的:这里没有涉及API键。当您使用不受信任的环境(例如:移动应用程序或客户端javascript应用程序)时,存储永久API令牌是完全不安全的——原因是它们可以很容易地从源代码或javascript中提取

    使用上述流程更安全,因为您可以获得很多保护:

    • 没有永久凭据存储在不安全的位置
    • 短寿命令牌用作标识符。它们会随着时间的推移而旋转
    • 令牌存储在Javascript无法访问的cookie中。这意味着更少的网络曝光风险
    • 在会话期间,密码只交换一次——这意味着敏感度较低的信息通过网络传输的频率较低=)
    无论如何:希望这有帮助


    而且,如果您正在寻找一些工具,任何oauth库(服务器端)都应该可以帮助您完成这些工作。如果您正在寻找一种可以为您做到这一点的服务,您可能需要查看我所使用的产品()。这是一项付费服务,但它代表您处理了很多这种复杂性。

    这个用例很有趣,我认为对于许多电子商务网站来说是一个问题。事实上,我正在从事的这项工作与那些试图在移动领域处理这类事情的公司进行了一些对话。用户登录可以用来告诉您谁在使用API,但是如果您不想强制人们使用用户名/登录,则必须搜索其他解决方案。您似乎想要的是一种识别哪些软件试图使用您的API的方法

    有两种简单的方法通常用于解决此问题:

    嵌入的秘密

    您可以向应用程序中添加密钥,并要求对API的任何访问都使用该密钥进行标识。人们会告诉你不要这样做,因为提取密钥非常容易。这是真的,但是对于所有的安全性,都需要进行成本/收益分析,以评估您要投入多少工作来保护您的API。javascript的问题在于,混淆或隐藏秘密并不是那么容易,因为所有的源代码都在那里

    如果你正在考虑一个你有其他语言选择的环境,那么你可以做更多的事情来混淆你应用程序中的秘密(比如在android中使用NDK)。不过Javascript很难

    使用API密钥需要记住的重要一点是,您永远不应该以明文形式传输它。那样偷东西真的很容易。相反,您可以使用密钥对API通信进行签名,以便服务器可以验证请求是否来自具有密钥的对象,并且知道如何对其进行签名

    速率限制

    虽然实际上并不是问题的解决方案,但这取决于你试图实现的目标