[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位補零知識點,可以
參考'http://www.hmoore.net/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 -- 案例
- 待續