至少特权的原则是零信任框架的基础组成部分。这些框架倡导组织不应自动信任其基础架构外部或之外的活动。
它要求组织设置和部署严格的身份验证和授权协议,并仅授予执行任务到连接到其远程或本地系统的设备所需的必要访问。
许多组织正在加速其数字化转型策略,从而从传统的周边安全方法转移到零信任框架以保护其最敏感的网络。
该作品将使用Firebase(一个应用程序开发平台,可帮助您构建和发展应用程序和游戏用户Love and Node.js®(一种开源的,跨平台Javascript运行时环境)。在此处查看part 2。
一个人可能会问,为什么特权的原则很重要?下面提供了一些答案:
- 它减少了网络攻击表面。
- 它停止了恶意软件的传播。
- 它提高了最终用户的生产率。
- 它有助于简化合规性和审核。
简单的项目设置将用于使教程尽可能基本。但是,可以将相同的方法扩展并应用于更复杂的企业SaaS应用程序。代码树如下所示:
.
├── README.md
├── controllers
│ └── user.js
├── database
│ └── index.js
├── index.js
├── lib
│ └── auth.js
├── migrate.js
├── package-lock.json
├── package.json
├── permission.json
└── routes
└── user.js
在这里,我们有四个目录:controllers
,routes
,database
and lib
。如前所述,通过使用单个用户路由来简化设置。控制器目录具有带有端点回调函数的user.js
文件。虽然路线目录有各种端点要执行CRUD
操作。
LIB目录具有与身份验证相关功能的auth.js
文件。其他文件是index.js
文件,众所周知,该文件是项目的入口点。 permission.json
是另一个重要的文件,因为它包含firebase服务帐户设置。
数据库具有带有用户角色的模拟数据。使用Firebase getAuth
方法的setCustomUserClaims
将用户角色分配给用户。模拟数据由用户对象和以下模式组成:
{
id: '1',
username: 'janedoe',
displayName: 'Jane Doe',
email: 'jane.doe@permission.com',
password: 'password',
phoneNumber: '+2348030004001',
photoURL: 'http://avatar.png',
emailVerified: true,
disabled: false,
role: {
name: "User",
entity: "isUser",
permissions: [
{ name: "create", value: false, },
{ name: "readAll", value: false },
{ name: "read", value: true, },
{ name: "update", value: true, },
{ name: "delete", value: false, },
],
},
created_at: 1673431871000,
updated_at: 1673431871000,
}
正如我们所看到的,角色变量具有name
,entity
,permissions
等。权限变量也是name
和value
的键值对数组,即细粒度访问权限。该名称是预期的操作,而该值是执行此类操作的特权。
然后,有一个migration.js
文件,用于将数据播种到firebase身份验证表中。最后,具有用于启动和迁移模拟数据的脚本对象的package.json
文件。要迁移模拟数据,请运行命令npm run migration up
。 (N.B:确保您不跳过命令中的最后一个 up )。
"scripts": {
"start": "node index.js",
"dev": "nodemon -r dotenv/config index.js",
"migration": "node migrate.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
项目集有五个端点:getUsers
,getUser
,addUser
,updateUser
和deleteUser
。这些端点中的每一个都有相应的动作:readAll
,read
,create
,update
和delete
。如前所述,此实现的简单性是出于演示目的。
auth.js文件具有两个主要功能定义。 isAuthenticated
函数用于身份验证和授权的isUser
功能。此角色将在帐户创建步骤中添加到帐户自定义索赔中。
/**
* [START CHECK USER]
* @param {object} req Express request context.
* @param {object} res Express response context.
* @param {object} next Express next context.
*/
exports.isUser = (action) => (req, res, next) => {
getAuthToken(req, res, async () => {
try {
// TODO: get and verify authToken
const { authToken } = req;
const userInfo = await getAuth().verifyIdToken(authToken);
// TODO: user has permission required to perform action on any API method
const allow = userInfo.permissions.some(permission => permission.name === action && permission.value === true);
// TODO: user not allowed to take action
if (!allow) return res.status(403).json('Forbidden access!!');
// TODO: user allowed to take action
req.user = userInfo;
return next();
}
catch (error) {
return res.status(401).json('Unauthorized access!');
}
});
}
// [END CHECK USER]
我敢肯定,这是非常解释的。 action
参数用于确定预期的任务,以及用户是否提出请求或期望响应具有正确的许可。这些权限和相应的身份验证功能用于对请求和响应进行身份验证和授权。
isAuthenticated
作为index.js
中的应用程序中间件传递,以身份验证请求。当isUser
角色及其相关权限之前通过回调功能作为每个路由端点上的中间件,以授权用户操作。
这是关于在服务器上API端点上设置最低特权的原理。接下来,我们将介绍如何将其与客户端挂钩以对用户进行身份验证并授权执行操作。本教程的存储库在github上。
如果您喜欢这篇文章,请喜欢并与朋友分享。