[TOC]
>[success] # 权限验证
~~~
1.利用'JS--按位运算'的形式做权限控制,说明其他语言原理是一样的,这里是针对js说明实践
~~~
>[danger] ##### 举例子
~~~
1.现在有个需求不同用户有不同的权限来设置增删改查,即A用户可能具备'增删',B用户可以能具备'增查',
将其转换二级制的思想,'1111' 表示拥有所有权限,增'1000',删'0100',改'0010',查'0001',那么增查可以
看作'1001',简单的理解为'1' 有权限,'0' 为没权限,则在不同位置表示他们所表示的对应权限
~~~
>[info] ## 了解按位运算
~~~
1. & 按位与
2. | 按位或
3. ^ 按位异或
4. ~ 按位非
5. <<左移
6. >>有符号右移
7. >>>无符号右移
~~~
>[danger] ##### << -- 左移
~~~
1.左移操作符 (<<) 将第一个操作数向左移动指定位数,左边超出的位数将会被清除,右边将会补零
2.左移的计算公式为 'x<<y' ===> 'x * 2 ** y',举个例子 9 << 3 等价于 9 * 2 ** 3 = 9 * 8 = 72
~~~
* 案例应用
~~~
1.所有权限码的二进制数形式,有且只有一位值为 1,其余全部为 0(2^n)简单的说
(位数上只有一位是1其余位为0)
2.符合上述条件的值都是 '2^n' ,采用左移表示
'1 << 0' ==> 1*2**0 ==> 转换二进制为 0001
'1 << 1' ==> 1*2**1 ==> 转换二进制为 0010
'1 << 2' ==> 1*2**2 ==> 转换二进制为 0100
~~~
>[danger] ##### | -- 按位或
~~~
1.参加运算的两个数只要两个数中的一个为1,结果就为1
2.举个例子二进制'0001'、'0010'通过'按位或'运算
0001
0010
结果为 0011
利用 '2^n' 特点即每一位只存在一个1,再利用'按位或'两个数中的一个为1,结果就为1的特点就可以
做到组合权限的一个数值代表
~~~
>[danger] ##### & -- 按位与
~~~
1.只有两个数的二进制同时为1,结果才为1,否则为0
2.举个例子二进制'0001'、'0010'通过'按位或'运算
0001
0011
结果为 0001
利用 '2^n' 特点即每一位只存在一个1,我们如果组合权限利用'按位计算'例如'0001'、'0010'得到'0011'
再利用'按位与'的特性就可以查出该权限是否在总权限中,也就是现在用户权限为'0011' 我想查询'0001'
因为对位为1的缘故所以0001 是在权限0011 中的
~~~
>[danger] ##### ~ -- 按位非
~~~
1.~ 运算符是对位求反,1变0, 0变1,也就是求二进制的反码。
2.举个例子1的二进制表示为: 00000000 00000000 00000000 00000001,这里涉及到js 32位补零知识点,可以
参考'https://www.kancloud.cn/cyyspring/more/1395853',对其位数取反得到11111111 11111111 11111111 11111101
如果你看了参考文章你就知道首位 1 表示为负数,0表示为正数,所以'~1' 按位非得到的是-2
3.简单记忆:一个数与自身的取反值相加等于-1
4.利用'按位非' 和 '按位与' 可以实现'删除一项或多项权限' ,例如你现在拥有的权限为'0011' 你想删除权限'0001'
此时利用'按位非' 对'0001'进行计算得到'1110',再利用'按位与' 将'1110' 和'0011' 计算得到'0010'
5.带有具体内容设计时候可以
static SELECT = {
value: 1 << 0,
info: "用户编辑权限"
},
这样在查询全部时候可以依次循环权限配置得到结果
~~~
>[danger] ##### 设计一个权限管理
~~~
class Permission {
// 是否允许查询,二进制第1位,0表示否,1表示是
static SELECT = 1 << 0; // 0001
// 是否允许新增,二进制第2位,0表示否,1表示是
static INSERT = 1 << 1; // 0010
// 是否允许修改,二进制第3位,0表示否,1表示是
static UPDATE = 1 << 2; // 0100
// 是否允许删除,二进制第4位,0表示否,1表示是
static REMOVE = 1 << 3; // 1000
// 存储目前的权限状态
static TEST = 1<<4; // 10000
constructor() {
this.flag = 0;
}
/**
* 重新设置权限
*/
setPermission(permission) {
this.flag = permission;
}
/**
* 添加一项或多项权限
*/
enable(permission) {
this.flag |= permission;
}
/**
* 删除一项或多项权限
*/
disable(permission) {
this.flag &= ~permission;
}
/**
* 是否拥某些权限
*/
isAllow(permission) {
return (this.flag & permission) == permission;
}
/**
* 是否禁用了某些权限
*/
isNotAllow(permission) {
return (this.flag & permission) == 0;
}
/**
* 是否仅仅拥有某些权限
*/
isOnlyAllow(permission) {
return this.flag == permission;
}
}
~~~
* vue 为例一个小案例
~~~
<template>
<div>
<p>权限:</p>
<section>
<label><input v-model="query" type="checkbox" value="" />查询 </label>
<label><input v-model="insert" type="checkbox" value="" />增加 </label>
<label><input v-model="remove" type="checkbox" value="" />删除 </label>
<label><input v-model="update" type="checkbox" value="" />更新 </label>
<label><input v-model="test" type="checkbox" value="" />测试 </label>
</section>
<section>权限值:{{ permission.flag }}</section>
</div>
</template>
<script>
// @ is an alias to /src
class Permission {
// 是否允许查询,二进制第1位,0表示否,1表示是
static SELECT = 1 << 0; // 0001
// 是否允许新增,二进制第2位,0表示否,1表示是
static INSERT = 1 << 1; // 0010
// 是否允许修改,二进制第3位,0表示否,1表示是
static UPDATE = 1 << 2; // 0100
// 是否允许删除,二进制第4位,0表示否,1表示是
static REMOVE = 1 << 3; // 1000
// 存储目前的权限状态
static TEST = 1 << 4;
constructor() {
this.flag = 0;
}
/**
* 重新设置权限
*/
setPermission(permission) {
this.flag = permission;
}
/**
* 添加一项或多项权限
*/
enable(permission) {
this.flag |= permission;
}
/**
* 删除一项或多项权限
*/
disable(permission) {
this.flag &= ~permission;
}
/**
* 是否拥某些权限
*/
isAllow(permission) {
console.log(this.flag);
console.log(permission);
return (this.flag & permission) == permission;
}
/**
* 是否禁用了某些权限
*/
isNotAllow(permission) {
return (this.flag & permission) == 0;
}
/**
* 是否仅仅拥有某些权限
*/
isOnlyAllow(permission) {
console.log(permission, this.flag);
return this.flag == permission;
}
}
export default {
name: "Lab",
data() {
return {
insert: false,
update: false,
remove: false,
query: false,
test: false,
permission: new Permission(),
};
},
created() {
this.$watch("insert", (val) => {
if (val) {
this.permission.enable(Permission.INSERT);
} else {
this.permission.disable(Permission.INSERT);
}
console.log("INSERT>>>", this.permission.isAllow(Permission.INSERT));
});
this.$watch("update", (val) => {
if (val) {
this.permission.enable(Permission.UPDATE);
} else {
this.permission.disable(Permission.UPDATE);
}
console.log("UPDATE>>>", this.permission.isAllow(Permission.UPDATE));
});
this.$watch("remove", (val) => {
if (val) {
this.permission.enable(Permission.REMOVE);
} else {
this.permission.disable(Permission.REMOVE);
}
console.log("REMOVE>>>", this.permission.isAllow(Permission.REMOVE));
});
this.$watch("query", (val) => {
if (val) {
this.permission.enable(Permission.SELECT);
} else {
this.permission.disable(Permission.SELECT);
}
console.log("SELECT>>>", this.permission.isAllow(Permission.SELECT));
});
this.$watch("test", (val) => {
if (val) {
this.permission.enable(Permission.TEST);
} else {
this.permission.disable(Permission.TEST);
}
console.log("SELECT>>>", this.permission.isAllow(Permission.SELECT));
});
},
};
</script>
~~~
>[danger] ##### 判断数的奇偶
~~~
1.利用二进制偶数末尾为0 基数为1的特点和 1 进行'按位与判断'
~~~
~~~
// 偶数 & 1 = 0
// 奇数 & 1 = 1
console.log(2 & 1) // 0
console.log(3 & 1) // 1
~~~
>[info] ## 参考文章
[读读这个挺好 JavaScript 中的位运算和权限设计](https://juejin.cn/post/6844903988945485837#heading-9)
[位运算符在JS中的妙用](https://juejin.cn/post/6844903568906911752#heading-4)
[奇怪的知识——位掩码](https://juejin.cn/post/6931250132861648910#heading-12)
[「硬核JS」令你迷惑的位运算](https://juejin.cn/post/6900710763657166855#heading-31)
[巧用JS位运算](https://juejin.cn/post/6844903570584633351#heading-5)
- 工程化 -- Node
- vscode -- 插件
- vscode -- 代码片段
- 前端学会调试
- 谷歌浏览器调试技巧
- 权限验证
- 包管理工具 -- npm
- 常见的 npm ci 指令
- npm -- npm install安装包
- npm -- package.json
- npm -- 查看包版本信息
- npm - package-lock.json
- npm -- node_modules 层级
- npm -- 依赖包规则
- npm -- install 安装流程
- npx
- npm -- 发布自己的包
- 包管理工具 -- pnpm
- 模拟数据 -- Mock
- 页面渲染
- 渲染分析
- core.js && babel
- core.js -- 到底是什么
- 编译器那些术语
- 词法解析 -- tokenize
- 语法解析 -- ast
- 遍历节点 -- traverser
- 转换阶段、生成阶段略
- babel
- babel -- 初步上手之了解
- babel -- 初步上手之各种配置(preset-env)
- babel -- 初步上手之各种配置@babel/helpers
- babel -- 初步上手之各种配置@babel/runtime
- babel -- 初步上手之各种配置@babel/plugin-transform-runtime
- babel -- 初步上手之各种配置(babel-polyfills )(未来)
- babel -- 初步上手之各种配置 polyfill-service
- babel -- 初步上手之各种配置(@babel/polyfill )(过去式)
- babel -- 总结
- 各种工具
- 前端 -- 工程化
- 了解 -- Yeoman
- 使用 -- Yeoman
- 了解 -- Plop
- node cli -- 开发自己的脚手架工具
- 自动化构建工具
- Gulp
- 模块化打包工具为什么出现
- 模块化打包工具(新) -- webpack
- 简单使用 -- webpack
- 了解配置 -- webpack.config.js
- webpack -- loader 浅解
- loader -- 配置css模块解析
- loader -- 图片和字体(4.x)
- loader -- 图片和字体(5.x)
- loader -- 图片优化loader
- loader -- 配置解析js/ts
- webpack -- plugins 浅解
- eslit
- plugins -- CleanWebpackPlugin(4.x)
- plugins -- CleanWebpackPlugin(5.x)
- plugin -- HtmlWebpackPlugin
- plugin -- DefinePlugin 注入全局成员
- webapck -- 模块解析配置
- webpack -- 文件指纹了解
- webpack -- 开发环境运行构建
- webpack -- 项目环境划分
- 模块化打包工具 -- webpack
- webpack -- 打包文件是个啥
- webpack -- 基础配置项用法
- webpack4.x系列学习
- webpack -- 常见loader加载器
- webpack -- 移动端px转rem处理
- 开发一个自己loader
- webpack -- plugin插件
- webpack -- 文件指纹
- webpack -- 压缩css和html构建
- webpack -- 清里构建包
- webpack -- 复制静态文件
- webpack -- 自定义插件
- wepack -- 关于静态资源内联
- webpack -- source map 对照包
- webpack -- 环境划分构建
- webpack -- 项目构建控制台输出
- webpack -- 项目分析
- webpack -- 编译提速优护体积
- 提速 -- 编译阶段
- webpack -- 项目优化
- webpack -- DefinePlugin 注入全局成员
- webpack -- 代码分割
- webpack -- 页面资源提取
- webpack -- import按需引入
- webpack -- 摇树
- webpack -- 多页面打包
- webpack -- eslint
- webpack -- srr打包后续看
- webpack -- 构建一个自己的配置后续看
- webpack -- 打包组件和基础库
- webpack -- 源码
- webpack -- 启动都做了什么
- webpack -- cli做了什么
- webpack - 5
- 模块化打包工具 -- Rollup
- 工程化搭建代码规范
- 规范化标准--Eslint
- eslint -- 扩展配置
- eslint -- 指令
- eslint -- vscode
- eslint -- 原理
- Prettier -- 格式化代码工具
- EditorConfig -- 编辑器编码风格
- 检查提交代码是否符合检查配置
- 整体流程总结
- 微前端
- single-spa
- 简单上手 -- single-spa
- 快速理解systemjs
- single-sap 不使用systemjs
- monorepo -- 工程
- Vue -- 响应式了解
- Vue2.x -- 源码分析
- 发布订阅和观察者模式
- 简单 -- 了解响应式模型(一)
- 简单 -- 了解响应式模型(二)
- 简单 --了解虚拟DOM(一)
- 简单 --了解虚拟DOM(二)
- 简单 --了解diff算法
- 简单 --了解nextick
- Snabbdom -- 理解虚拟dom和diff算法
- Snabbdom -- h函数
- Snabbdom - Vnode 函数
- Snabbdom -- init 函数
- Snabbdom -- patch 函数
- 手写 -- 虚拟dom渲染
- Vue -- minVue
- vue3.x -- 源码分析
- 分析 -- reactivity
- 好文
- grpc -- 浏览器使用gRPC
- grcp-web -- 案例
- 待续