如何保护客户端应用程序(反应)和 API 通信

问题描述:

我有一个客户端 React 应用程序和一个 Rails API,React 应用程序从中获取数据.

I have a client side React application and a Rails API from which the React app is fetching data.

如您所料,我只希望我的 React 应用程序能够从 API 获取数据,而世界其他地方不应该能够从它接收数据.

As you would expect I only want my React application to be able to fetch data from the API and the rest of the world shouldn't be able to receive data from it.

尽管进行了大量搜索,我仍未找到保护两个应用程序之间通信的最佳方法.

Despite much searching I am yet to find the best way to secure the communication between the two applications.

我已经阅读了有关 JWT 令牌和基于 cookie 的会话身份验证的文章,但大多数文章似乎都侧重于用户身份验证(即登录/注销),而不仅仅是两个应用程序之间的通信.

I have read about JWT tokens and cookie based session authentication but the majority of articles seem to be focused on authentication of users (ie sign in/sign out) rather than communication between just the two applications.

这两个应用将共享同一个域,那么依靠 Cross Origin 来确保通信安全就足够了吗?

The two apps will share the same domain so is it enough to rely on Cross Origin to secure communication?

任何建议真的将不胜感激.

Any advice really would be much appreciated.

如果我答对了您的问题,您希望您的客户端(React App)成为唯一可以访问您的服务器的客户端.

If I got your question right you want your client(React App) to be the only client who can access your server.

作为解决方案,您必须结合使用 CORS 和 JWT 授权,因此我建议使用严格的 CORS 以仅启用您的 React 应用程序的域来调用服务器.为了实现这一点,我通常使用 CORS npm 模块和 configure 我服务器上的源,或者您也可以自己完成.

As a solution to that you will have to have a combination of CORS and a JWT authorization, Thus I would suggest having a strict CORS to enable only your react app's domain to make a call to the server. To achieve this, I generally use a CORS npm module and configure the origin on my server or you can do it yourself as well.

var express = require('express')
var cors = require('cors')
var app = express()

var corsOptions = {
  origin: 'http://example.com',
  optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204 
}

上面的代码只允许服务器接受来自example.com的请求或者查看此代码 用于更多动态白名单 &黑名单方法.

The above code allows only requests from example.com to be accepted by the server or have a look at this code for more dynamic whitelist & blacklist approach.

现在回到 JWT,它只是一个 json 加密和解密令牌,可以跨 API 请求共享以进行身份​​验证和授权用户.

Now coming back to JWT, It is just a json encryption and decryption token which can share across API request to Authenticate as well as authorize the user.

例如,您可以在 JWT 中存储用户的电子邮件、角色和昵称等信息,并在每个 API 请求中发送此加密的 JWT,服务器对此请求进行授权,如果为 true,则转发到请求的 API.这个授权和转发过程通常使用拦截器"模式实现,其中一个中间件(Passport oAuth) 在每次 API 调用之前进行检查和验证.

For instance, you can store information like email, role, and nickname of the user in JWT and sent this encrypted JWT in each API request, the server authorizes this request and if true forwards to the requested API. This process of authorization and forwarding is generally implemented using an 'Interceptor' pattern wherein a middleware(Passport oAuth) does the check and auth before each API call.

执行上述 2 件事将确保只有具有有效 JWT 令牌和域地址的客户端才能与服务器通信.这个客户端将成为你的 React 应用程序,因为它是唯一一个拥有正确 JWT 和源地址的应用程序.

Doing the above 2 things will ensure that only a client which has valid JWT token and domain address which you allowed to talk with the server. And this client will be your react app, as it is the only one with proper JWT and origin address.

所以现在你的反应应用程序应该确保在 API 调用(post/get/put)中传递适当的 JWT 令牌,很可能在 API 请求的标头中,你可以有一个 API 帮助服务来执行此操作为您并在组件中导入它 - 无论您在哪里进行 API 调用.并且您的节点服务器将实现通行证中间件模式来授权此 JWT 并过滤未授权的请求.

So now your react app should just make sure that appropriate JWT token is passed in the API calls (post/get/put), most probably in the header of the API request, you can have an API helper service which does this for you and import that in component where-ever you make an API call. And your node server will implement the passport middleware pattern to authorize this JWT and filter non-authorized requests.

如果您的 React 应用程序没有登录名,则 JWT 也可以是一个客户端 ID,用于识别您的客户端是合法的.就像用户登录一样,您可以让您的应用程序使用诸如机密客户端 ID 之类的数据来调用服务器.这将返回一个 JWT 令牌.或者,您可以预先生成 JWT 令牌,并在第一次加载时反应应用程序存储它,通过设置 TTL 和另一个配置,您可以检查正在调用您的服务器的客户端是旧的还是新的还是其他的假客户.

If you react app doesn't have a login, The JWT can be a client ID as well which recognizes your client as being legit. And just like user login, you can have you react app make a call to the server with data like a secret client id. This will return a JWT token. OR you can pre-generate a JWT token and you react app store it when it loads the first time, and by setting TTL and another config you can check if the Client which is making a call to your server is Old or New or some other fake client.

HTH