如何使用node.js实现安全的REST API

I start planning a REST API with node.js ,express and mongodb. The API provides data for a website (public and private area) and maybe later a mobile app. The frontend will be developed with AngularJS.

For some days I read a lot about securing REST APIs, but I don’t get to a final solution. As far as I understand is to use HTTPS to provide a basic security. But how I can protect the API in that use cases:

  • Only visitors/users of the website/app are allowed to get data for the public area of the website/app

  • Only authenticated and authorized users are allowed to get data for private area (and only data, where the user granted permissions)

At the moment I think about to only allow users with a active session to use the API. To authorize the users I will use passport and for permission I need to implement something for myself. All on the top of HTTPS.

有人可以提供一些最佳实践或经验吗?我的“体系结构”是否缺乏?

2020/03/23 15:22:50

如果您想保护您的应用程序安全,那么绝对应该从使用HTTPS而不是HTTP开始,这可以确保在您和用户之间创建安全的通道,从而防止嗅探来回发送给用户的数据并有助于保留数据。交换了机密。

您可以使用JWT(JSON Web令牌)来保护RESTful API,与服务器端会话相比,这有很多好处,主要包括:

1-更具可扩展性,因为您的API服务器将不必为每个用户维护会话(当您有很多会话时,这可能是一个沉重的负担)

2-JWT是自包含的,并且具有定义用户角色的声明,例如,他可以在日期和到期日访问和发布的内容(此日期之后,JWT将无效)

3-更易于处理负载均衡器,并且如果您有多个API服务器,因为您不必共享会话数据,也无需配置服务器将会话路由到同一服务器,那么只要JWT的请求碰到任何服务器,就可以对其进行身份验证和授权

4-减轻了数据库负担,也不必为每个请求不断存储和检索会话ID和数据

5-如果您使用强键对JWT进行签名,则JWT不会被篡改,因此您可以信任随请求一起发送的JWT中的声明,而无需检查用户会话以及他是否被授权,您只需检查JWT,然后就可以知道该用户可以执行的操作。

许多库提供了使用大多数编程语言创建和验证JWT的简便方法,例如:在node.js中,最受欢迎的一种是jsonwebtoken

由于REST API通常旨在使服务器保持无状态,因此JWT与该概念更加兼容,因为每个请求都是使用自包含(JWT)的授权令牌发送的,而与服务器会话相比,服务器不必跟踪用户会话服务器是有状态的,以便记住用户及其角色,但是,会话也被广泛使用并具有其优点,您可以根据需要进行搜索。

需要注意的重要一件事是,您必须使用HTTPS将JWT安全地交付给客户端,并将其保存在安全的地方(例如,本地存储中)。

您可以从此链接了解有关JWT的更多信息。

2020/03/23 15:22:50

我遇到了与您描述的问题相同的问题。我正在建立的网站可以通过手机和浏览器访问,因此我需要一个API来允许用户注册,登录和执行某些特定任务。此外,我需要支持可伸缩性,同一代码运行在不同的进程/机器上。

由于用户可以创建资源(也称为POST / PUT操作),因此需要保护api。您可以使用oauth或构建自己的解决方案,但请记住,如果密码很容易发现,则所有解决方案都可能被破坏。基本思想是使用用户名,密码和令牌(即apitoken)对用户进行身份验证。可以使用node-uuid生成此apitoken,并可以使用pbkdf2哈希密码

然后,您需要将会话保存在某个地方。如果将其保存在一个普通对象的内存中,如果您杀死服务器并再次重新启动它,则会话将被破坏。同样,这是不可扩展的。如果使用haproxy在计算机之间进行负载平衡,或者仅使用worker,则此会话状态将存储在单个进程中,因此,如果将同一用户重定向到另一个进程/计算机,则需要再次进行身份验证。因此,您需要将会话存储在一个公共位置。通常使用redis完成此操作。

验证用户身份(用户名+密码+ apitoken)后,为会话生成另一个令牌,也称为accesstoken。同样,使用node-uuid。向用户发送访问令牌和用户标识。用户ID(密钥)和访问令牌(值)存储在redis中并带有到期时间,例如1h。

现在,每次用户使用rest api进行任何操作时,都需要发送userid和accesstoken。

如果您允许用户使用其余的api注册,则需要使用admin apitoken创建一个管理员帐户并将其存储在移动应用中(加密用户名+密码+ apitoken),因为新用户在以下情况下将没有apitoken他们注册。

网络上也使用此api,但您无需使用apitokens。您可以对redis存储区使用express,也可以使用与上述相同的技术,但是绕过apitoken检查并向用户返回cookie中的userid + accesstoken。

如果您有私人区域,则在验证用户名时将其与允许的用户进行比较。您还可以将角色应用于用户。

摘要:

顺序图

An alternative without apitoken would be to use HTTPS and to send the username and password in the Authorization header and cache the username in redis.

Itachi2020/03/23 15:22:50

如果您希望Web应用程序具有完全锁定的区域,而该区域只能由公司的管理员访问,则可以为您提供SSL授权。这将确保没有人可以连接到服务器实例,除非他们在浏览器中安装了授权证书。上周,我写了一篇有关如何设置服务器的文章

这是您将找到的最安全的设置之一,因为其中不涉及用户名/密码,因此除非您的用户之一将密钥文件交给潜在的黑客,否则任何人都无法获得访问权限。

Mandy2020/03/23 15:22:50

关于SO的REST身份验证模式有很多问题。这些与您的问题最相关:

基本上,您需要选择使用API​​密钥(最不安全,因为密钥可能被未经授权的用户发现),应用程序密钥和令牌组合(中)或完整的OAuth实施(最安全)之间进行选择。

凯西里2020/03/23 15:22:50

我刚刚完成了一个示例应用程序,该应用程序以一种非常基本但清晰的方式进行了此操作。它使用mongoose和mongodb来存储用户和护照以进行身份​​验证管理。

https://github.com/Khelldar/Angular-Express-Train-Seed