如何配置ESLint规则禁止代码中出现指定违规值——权限控制模块代码合规校验技术问询
解决方案:用ESLint禁止代码中直接使用角色/身份属性(允许注释)
我刚好遇到过类似的权限控制规范落地需求,下面给你两种靠谱的实现方案,既满足你的要求,又能灵活扩展:
方案一:用ESLint内置规则快速实现
如果你只需要覆盖你提到的两种场景(访问user.isSuperAdmin、硬编码'superadmin'字符串),用ESLint自带的规则组合就能搞定,不需要写自定义规则:
1. 禁止访问特定用户属性(比如isSuperAdmin)
使用no-restricted-properties规则,专门用来禁止访问对象的特定属性:
// .eslintrc.json { "rules": { "no-restricted-properties": [ "error", { "object": "user", "property": "isSuperAdmin", "message": "禁止直接判断用户是否为超级管理员,请基于权限列表进行操作" } // 可以添加更多禁止的属性,比如: // { "object": "user", "property": "isAdmin", "message": "..." } ] } }
这个规则会拦截所有user.isSuperAdmin的访问(不管是在if条件还是其他地方),但不会影响注释里的内容。
2. 禁止硬编码角色字符串(比如'superadmin')
使用no-restricted-strings规则,它默认忽略注释中的字符串,完美符合你的需求:
// .eslintrc.json { "rules": { "no-restricted-strings": [ "error", { "pattern": "^superadmin$", "message": "禁止直接使用角色标识'superadmin',请基于权限列表进行操作" }, // 可以添加更多禁止的角色,比如精确匹配'admin': // "admin", // 或者用正则匹配多个: // { "pattern": "^(editor|viewer)$", "message": "..." } ] } }
这个规则会拦截代码中所有'superadmin'或"superadmin"的字面量,但注释里的// superadmin不会触发错误。
把这两个规则组合起来,就能覆盖你给出的两个违规示例了。
方案二:自定义ESLint规则(应对复杂场景)
如果你的场景更复杂(比如要拦截user.role.includes('superadmin')、currentUser.isSuperAdmin这类情况),可以写一个自定义规则,灵活性更高:
1. 编写自定义规则
创建一个eslint-rules/no-role-checks.js文件,内容如下:
module.exports = { meta: { type: 'problem', docs: { description: '禁止直接基于角色或用户身份进行权限判断,必须使用权限列表', recommended: true }, messages: { restrictedProperty: '禁止访问用户属性{{property}},请基于权限列表进行操作', restrictedRole: '禁止使用角色标识{{role}},请基于权限列表进行操作' }, schema: [ { type: 'object', properties: { restrictedProperties: { type: 'array', items: { type: 'string' } }, restrictedRoles: { type: 'array', items: { type: 'string' } } } } ] }, create(context) { const options = context.options[0] || {}; const restrictedProperties = options.restrictedProperties || ['isSuperAdmin']; const restrictedRoles = options.restrictedRoles || ['superadmin']; return { // 拦截用户对象的特定属性访问 MemberExpression(node) { // 这里可以根据你的实际情况修改,比如支持currentUser、ctx.user等 const allowedUserObjects = ['user', 'currentUser', 'ctx.user']; const objectName = node.object.type === 'Identifier' ? node.object.name : (node.object.type === 'MemberExpression' ? `${node.object.object.name}.${node.object.property.name}` : ''); if (allowedUserObjects.includes(objectName) && node.property.type === 'Identifier' && restrictedProperties.includes(node.property.name)) { context.report({ node, messageId: 'restrictedProperty', data: { property: node.property.name } }); } }, // 拦截特定角色字符串字面量(排除注释) Literal(node) { if (typeof node.value === 'string' && restrictedRoles.includes(node.value)) { // 检查当前字符串是否在注释范围内 const sourceCode = context.getSourceCode(); const isInComment = sourceCode.getCommentsBefore(node).some(comment => comment.range[1] >= node.range[0]) || sourceCode.getCommentsAfter(node).some(comment => comment.range[0] <= node.range[1]); if (!isInComment) { context.report({ node, messageId: 'restrictedRole', data: { role: node.value } }); } } } }; } };
2. 引入自定义规则
在package.json中添加本地插件的映射:
{ "eslint-plugin-local": "file:./eslint-rules" }
然后在ESLint配置中启用这个规则:
// .eslintrc.json { "plugins": ["local"], "rules": { "local/no-role-checks": [ "error", { "restrictedProperties": ["isSuperAdmin", "isAdmin"], "restrictedRoles": ["superadmin", "admin", "editor"] } ] } }
这个自定义规则可以灵活扩展,比如支持更多用户对象的命名(currentUser、ctx.user),或者拦截更复杂的表达式。
内容的提问来源于stack exchange,提问作者link89
相关产品推荐
相关产品推荐

