我开始计划一个带有 node 的REST API.js、express和mongodb.该API为网站(公共和私有区域)以及以后的移动应用程序提供数据.前端将由AngularJS开发.

有几天我读了很多关于保护REST API的书,但没有找到最终的解决方案.据我所知是使用HTTPS来提供基本的安全性.但我如何在这种情况下保护API:

  • 只有网站/应用程序的访问者/用户才能获取网站/应用程序公共区域的数据

  • 只有经过身份验证和授权的用户才能获取私有区域的数据(并且只有用户授予权限的数据)

目前,我考虑只允许具有活动会话的用户使用API.为了授权用户,我将使用passport,为了获得许可,我需要为自己实现一些东西.都在HTTPS之上.

有人能提供一些最佳实践或经验吗?我的"架构"中是否存在缺陷?

推荐答案

我也有你描述的问题.我正在创建的网站可以通过手机和浏览器访问,因此我需要一个api,允许用户注册、登录和执行一些特定任务.此外,我需要支持可伸缩性,在不同的进程/机器上运行相同的代码.

因为用户可以创建保护api所需的资源(也称为POST/PUT操作).您可以使用oauth,也可以构建自己的解决方案,但请记住,如果密码很容易被发现,那么所有解决方案都可能被破解.其基本思想是使用用户名、密码和令牌(也称为apitoken)对用户进行身份验证.这个apitoken可以使用node-uuid生成,密码可以使用pbkdf2散列

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

当用户通过身份验证(用户名+密码+apitoken)时,为会话生成另一个令牌,即accesstoken.同样,使用 node uuid.向用户发送accesstoken和userid.用户ID(密钥)和accesstoken(值)存储在redis中,并具有有效期和过期时间,例如1h.

现在,每当用户使用rest api执行任何操作时,都需要发送用户ID和accesstoken.

如果您允许用户使用rest api注册,则需要使用admin Apitonk创建一个admin帐户,并将其存储在移动应用程序中(加密用户名+密码+Apitonk),因为新用户注册时不会有Apitonk.

web也使用此api,但不需要使用APIToken.您可以将express与redis store一起使用,也可以使用上述相同的技术,但可以绕过apitoken判断,将cookie中的userid+accesstoken返回给用户.

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

总结:

序列图

没有apitoken的另一种 Select 是使用HTTPS,在授权头中发送用户名和密码,并在redis中缓存用户名.

Node.js相关问答推荐

无法在我的 node 项目中转让Google Drive v3 API中的所有权

Mongoose-如何从父文档填充到子文档

为什么在导出的函数中调用node-sqlite3中的数据库方法时不起作用?

JsonwebToken过期后如何注销和清除cookie?

谷歌应用程序脚本UrlFetchApp和nodejs-axios返回不同的结果;MyFitnessPal日记

在 Nest 项目上运行 Jest 测试时,我的文件无法找到一个在测试之外没有任何问题的模块

如何避免在 mongodb 聚合中查找重复结果?

使用`useLocalStorage`和`useDebounce`时如何解决Next.js中的react-hydration-error

如何解决 npm install react-select failure with error : An unknown git error occurred, git@github.com :Permission denied (publickey)

nvm / node / npm: node 12 的 npm 比 node 14 的更新?

多个 Axios 请求合并

如何为一个网站实现这 2 个网址.即 www.administrator.sitename.com 和 www.sitename.com?

响应发送 200 而不是 403

编写可维护的事件驱动代码

使用 Webpack 和 font-face 加载字体

如何让should.be.false语法通过 jslint?

Bootstrap 中的 Grunt 依赖冲突

未在 Windows 8.1 上构建的 node 包 - 缺少 Microsoft.Cpp.Default.props

为什么 Node.js 没有原生 DOM?

将 expressjs 绑定到特定的 IP 地址