-Moody- - Moody
type: channel
link: https://coder.cm/index.php/author/1/
description: Moody
items: Rust 方法和特性概览
items: Android 证书获取 和 打release包
items: Office正版永久免费使用详细教程
items: Mac 51 单片机开发环境搭建
items: 如何实现jwt鉴权机制
items: 300+前端实用的库
items: Vue3 实现一个Modal 组件
items: SSH 连接
items: docker 简单入门。
items: vue权限管理之控制到按钮级别的权限

Rust 方法和特性概览
type: item
date: 2024-09-05T12:44:00+08:00
description: Rust 提供了多种内置方法和功能，涵盖了从基础数据类型操作到高级特性的一系列功能。一下是一些常见的Rust 方法和功能，分为不同类别：Rust 方法和特性1. 字符串操作push_str：追加一个字符串切片到字符串的末尾。push：向字符串末尾添加一个字符。to_string：将其他数据类型转换为字符串。trim：去除字符串两端的空白字符。split：按指定分隔符拆分字符串，返回迭代器。replace：将字符串中的指定子串替换为另一个子串。find：查找指定子串的起始索引，返回 Option<usize>。starts_with：判断字符串是否以指定子串开头。ends_with：判断字符串是否以指定子串结尾。len：返回字符串的字节长度。2. 向量（Vec）操作push：向向量中追加一个元素。pop：移除向量的最后一个元素并返回该元素。len：返回向量的长度（元素数量）。get：按索引获取元素，返回 Option<&T>。remove：移除并返回指定索引处的元素。contains：检查向量中是否包含指定元素。iter：返回一个不可变的迭代器。iter_mut：返回一个可变的迭代器。clear：清空向量。sort：对向量中的元素进行排序。extend：将另一个向量的元素追加到当前向量中。3. 数组操作len：返回数组的长度。get：按索引获取数组元素，返回 Option<&T>。iter：返回数组的迭代器。copy_from_slice：从另一个切片复制数据到数组。clone_from_slice：克隆另一个切片的内容到当前数组。4. 集合（HashMap、HashSet）4.1 HashMap 操作insert：将键值对插入哈希映射。get：根据键获取值，返回 Option<&V>。remove：根据键移除键值对。contains_key：检查是否存在指定键。len：返回哈希映射中的键值对数量。keys：返回哈希映射中的所有键的迭代器。values：返回哈希映射中的所有值的迭代器。4.2 HashSet 操作insert：向哈希集合中插入一个元素。remove：从哈希集合中移除指定元素。contains：检查哈希集合中是否包含某个元素。len：返回集合中的元素数量。5. 错误处理5.1 Result 类型Ok 和 Err：用于表示操作的结果枚举。unwrap：取出 Ok 值，若为 Err 则触发崩溃。expect：类似 unwrap，但允许自定义错误信息。map：对 Ok 值进行操作并返回新的 Result。and_then：链式操作，处理成功时的结果。unwrap_or：返回 Ok 值或提供的默认值。5.2 Option 类型Some 和 None：用于表示值可能存在或不存在。unwrap：取出 Some 值，若为 None 则崩溃。is_some 和 is_none：判断是否为 Some 或 None。map：对 Some 值进行操作并返回新的 Option。unwrap_or：返回 Some 值或提供的默认值。6. 迭代器next：获取迭代器中的下一个元素。filter：过滤迭代器中满足条件的元素。map：对迭代器中的每个元素进行操作，返回新的迭代器。collect：将迭代器转换为集合（如 Vec、HashMap）。fold：将迭代器中的元素累积到一个单一的结果中。enumerate：为迭代器中的元素附带索引。zip：将两个迭代器配对为一个新的迭代器。chain：将两个迭代器串联为一个新的迭代器。7. 并发编程std::thread：提供多线程支持。spawn：创建一个新线程并执行闭包。join：等待线程执行完成并获取其结果。std::sync::mpsc：用于线程之间的消息传递（单发送者，多接收者）。Mutex：提供线程间共享数据的安全访问。Arc：原子引用计数，允许在多线程间共享数据。8. 文件操作std::fs::File：用于文件的读写操作。read_to_string：读取文件内容并将其转换为字符串。write_all：将字节数组写入文件。create：创建一个新文件，若文件已存在则覆盖。open：打开现有文件。metadata：获取文件的元数据。9. 内存管理与所有权Box<T>：在堆上分配内存并返回一个指针。Rc<T>：引用计数智能指针，允许多个所有者。Arc<T>：线程安全的引用计数智能指针。RefCell<T>：提供运行时的内部可变性。Cow<T>：可以在只读和可变状态之间切换的智能指针。10. 常用工具10.1 cargo 命令cargo build：编译项目。cargo run：编译并运行项目。cargo test：运行测试。cargo doc：生成项目的文档。cargo clean：清理构建生成…

Android 证书获取 和 打release包
type: item
date: 2024-07-10T14:46:00+08:00
description: 1. 生成Android 证书keytool -genkey -alias testalias -keyalg RSA -keysize 2048 -validity 36500 -keystore test.keystore-alias 别名 这边使用 testalias代替test.keystor输入密钥库口令: //输入证书文件密码，输入完成回车 再次输入新口令: //再次输入证书文件密码，输入完成回车 您的名字与姓氏是什么? [Unknown]: //输入名字和姓氏，输入完成回车 您的组织单位名称是什么? [Unknown]: //输入组织单位名称，输入完成回车 您的组织名称是什么? [Unknown]: //输入组织名称，输入完成回车 您所在的城市或区域名称是什么? [Unknown]: //输入城市或区域名称，输入完成回车 您所在的省/市/自治区名称是什么? [Unknown]: //输入省/市/自治区名称，输入完成回车 该单位的双字母国家/地区代码是什么? [Unknown]: //输入国家/地区代号（两个字母），中国为CN，输入完成回车 CN=XX, OU=XX, O=XX, L=XX, ST=XX, C=CN是否正确? [否]: //确认上面输入的内容是否正确，输入y，回车 正在为以下对象生成 2,048 位RSA密钥对和自签名证书 (SHA256withRSA) (有效期为 36,500 天): CN=XX, OU=XX, O=XX, L=XX, ST=XX, C=CN2.查看证书keytool -list -v -keystore test.keystore Enter keystore password: //输入创建证书时的密码，回车密钥库类型: PKCS12 密钥库提供方: SUN 您的密钥库包含 1 个条目 别名: testalias 创建日期: 2024年7月10日 条目类型: PrivateKeyEntry 证书链长度: 1 证书[1]: 所有者: CN=XX, OU=XX, O=XX, L=XX, ST=XX, C=CN 发布者: CN=XX, OU=XX, O=XX, L=XX, ST=XX, C=CN 序列号: efd7bcf99g462f13 生效时间: Wed Jul 10 14:11:38 CST 2024, 失效时间: Fri Jun 16 14:11:38 CST 2124 证书指纹: SHA1: EA:8C:F5:E1:26:0B:89:69:F9:04:E3:D9:78:8B:0B:B8:13:45:F8:DA SHA256: 63:28:66:94:6B:08:51:3B:D1:EA:5C:D9:F0:DA:83:DA:9D:0E:C4:D1:4B:30:47:40:B2:23:30:AD:C1:E0:2F:86 签名算法名称: SHA256withRAA 主体公共密钥算法: 2048 位 RSA 密钥 版本: 3 扩展: #1: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: C9 06 CC 3F 9E B0 E7 58 88 DE 38 EA E3 65 42 0E ...?...X..8..eB. 0010: 69 23 BB 22 i#.. ] ]3.配置gradle.propertiesSYS_TEST_KEY_ALIAS=testalias SYS_TEST_KEY_PASSWORD=test2024 SYS_TEST_STORE_FILE=test.keystore SYS_TEST_STORE_PASSWORD=test20244.配置项目中的 build.gradle.ktsapp/buidl.gradle.ktssourceSets { getByName("main").res.srcDirs("src/main/res/font") } signingConfigs { create("release") { if (project.hasProperty("SYS_TEST_STORE_FILE")) { storeFile = file(project.property("SYS_TEST_STORE_FILE") as String) storePassword = project.property("SYS_TEST_KEY_PASSWORD") as String keyAlias = project.property("SYS_TEST_KEY_ALIAS") as String keyPassword = proje…

Office正版永久免费使用详细教程
type: item
date: 2024-05-28T23:25:00+08:00
description: 步骤1：访问Microsoft官网，下载官方部署工具Office Deployment Tool 微软官方地址：工具链接步骤2：运行 Office Depolyment Tool步骤3：通过Microsoft Office 自定义工具制作配置文件 微软官方地址：配置链接步骤4：将导出的config 文件存放到 office 文件中步骤5：激活 打开PowerShell 或者CMD 管理员运行 建议使用PowerShell 下载安装office比如我工具运行之后东西在 f盘的ofcd F:\of .\setup.exe /download config.xml // 等待下载安装文件 .\setup.exe /configure config.xml // 安装激活 打开PowerShell 或者CMD 管理员运行 建议使用PowerShellcd "C:\\Program Files\\Microsoft Office\\Office16" // 进到c盘找一定能找到 cscript ospp.vbs /sethst:kms.03k.org cscript ospp.vbs /act

Mac 51 单片机开发环境搭建
type: item
date: 2023-12-07T20:03:00+08:00
description: 1. Homebrew 包管理工具安装什么是homebrewhomebrew 是 Mac'Os系统里面的包管理工具，主要解决软件或者包下载时的各种依赖包。homebrew 下载安装// 官方源 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" // 或者国内源 选择中科大的源安装完成后 终端中输入 [font color="orange"]brew -v[/font] 如出现版本号代表安装成功2. 安装 SDCCsdcc (Small Device C Compiler) 是一个应用于单片机的一个交叉编译器，其官网上的解释是这样的SDCC is a retargettable, optimizing Standard C (ANSI C89, ISO C99, ISO C11) compiler suite that targets the Intel MCS51 based microprocessors (8031, 8032, 8051, 8052, etc.), Maxim (formerly Dallas) DS80C390 variants, Freescale (formerly Motorola) HC08 based (hc08, s08), Zilog Z80 based MCUs (z80, z180, gbz80, Rabbit 2000/3000, Rabbit 3000A, TLCS-90), Padauk (pdk14, pdk15) and STMicroelectronics STM8. Work is in progress on supporting the Padauk (pdk13), Microchip PIC16 and PIC18 targets. It can be retargeted for other microprocessors.brew install sdcc sdcc -v3. 安装 python3 和 stcgalbrew install python3 // 安装stcgal 执行pip install stcgal即可安装4. 安装ttl下载器的驱动这边提供两种方式安装1.官网下载安装 [font color="orange"]CH340[/font] 下载地址2.brew 安装（推荐）brew install --cask wch-ch34x-usb-serial-driver // 验证 连接单片机 // ll /dev/cu.wchusbserial140 比如我的.一般之后后三位不一样 ll /dev/cu.xxxxxxxxxxx5.编译main.c 并且转成 hex 格式sdcc main.c // ihx 转换 hex packihx main.ihx > main.hex // 下载到单片机中 stc89 为单片机协议 如出现 [font color="green"]Waiting for MCU, please cycle power:[/font]代表成功 此时按下 单片机的电源开关 重新启动单片机程序就会下载到单片机中

如何实现jwt鉴权机制
type: item
date: 2023-05-17T16:19:00+08:00
description: 一、是什么JWT（JSON Web Token），本质就是一个字符串书写规范，如下图，作用是用来在用户和服务器之间传递安全可靠的信息。在目前前后端分离的开发过程中，使用token鉴权机制用于身份验证是最常见的方案，流程如下：服务器当验证用户账号和密码正确的时候，给用户颁发一个令牌，这个令牌作为后续用户访问一些接口的凭证后续访问会根据这个令牌判断用户时候有权限进行访问Token，分成了三部分，头部（Header）、载荷（Payload）、签名（Signature），并以.进行拼接。其中头部和载荷都是以JSON格式存放数据，只是进行了编码header每个JWT都会带有头部信息，这里主要声明使用的算法。声明算法的字段名为alg，同时还有一个typ的字段，默认JWT即可。以下示例中算法为HS256{ "alg": "HS256", "typ": "JWT" }因为JWT是字符串，所以我们还需要对以上内容进行Base64编码，编码后字符串如下：eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9payload载荷即消息体，这里会存放实际的内容，也就是Token的数据声明，例如用户的id和name，默认情况下也会携带令牌的签发时间iat，通过还可以设置过期时间，如下：{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }同样进行Base64编码后，字符串如下：eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQSignature签名是对头部和载荷内容进行签名，一般情况，设置一个secretKey，对前两个的结果进行HMACSHA25算法，公式如下：Signature = HMACSHA256(base64Url(header)+.+base64Url(payload),secretKey)一旦前面两部分数据被篡改，只要服务器加密用的密钥没有泄露，得到的签名肯定和之前的签名不一致二、如何实现Token的使用分成了两部分：生成token：登录成功的时候，颁发token验证token：访问某些资源或者接口时，验证token生成 token借助第三方库jsonwebtoken，通过jsonwebtoken 的 sign 方法生成一个 token：第一个参数指的是 Payload第二个是秘钥，服务端特有第三个参数是 option，可以定义 token 过期时间const crypto = require("crypto"), jwt = require("jsonwebtoken"); // TODO:使用数据库 // 这里应该是用数据库存储，这里只是演示用 let userList = []; class UserController { // 用户登录 static async login(ctx) { const data = ctx.request.body; if (!data.name || !data.password) { return ctx.body = { code: "000002", message: "参数不合法" } } const result = userList.find(item => item.name === data.name && item.password === crypto.createHash('md5').update(data.password).digest('hex')) if (result) { // 生成token const token = jwt.sign( { name: result.name }, "test_token", // secret { expiresIn: 60 * 60 } // 过期时间：60 * 60 s ); return ctx.body = { code: "0", message: "登录成功", data: { token } }; } else { return ctx.body = { code: "000002", message: "用户名或密码错误" }; } } } module.exports = UserController;在前端接收到token后，一般情况会通过localStorage进行缓存，然后将token放到HTTP 请求头Authorization 中，关于Authorization 的设置，前面要加上 Bearer ，注意后面带有空格axios.interceptors.request.use(config => { const …

300+前端实用的库
type: item
date: 2023-02-08T11:49:00+08:00
description: 300+编程实用工具Javascript工具Underscore.js一套完善的函数式编程的接口，更方便地在JavaScript中实现函数式编程https://underscorejs.org/fastclick用于消除物理点击和click移动浏览器上事件触发之间的 300 毫秒延迟https://github.com/ftlabs/fastclickLodash一致性、模块化、高性能的 JavaScript 实用工具库https://lodash.com/crypto-js加密标准的 JavaScript 库。https://github.com/brix/crypto-jszxcvbnJavaScript密码强度估算库https://github.com/dropbox/zxcvbnzxcvbn-ts支持Typescript的密码强度估算库https://github.com/zxcvbn-ts/zxcvbnclipboard.js将文本复制到剪贴板的轻量级JS 库https://clipboardjs.com/tesseract.jsJavascript的OCR引擎，在浏览器离线识别图片中的文字https://tesseract.projectnaptha.com/number-precision小而快的库，用于精确地进行加法、减法、乘法和除法运算https://github.com/nefe/number-precisionfingerprintjs具有高准确度和稳定性的浏览器指纹库https://fingerprint.com/ViteShot基于Vite的快速简单的截图工具。https://viteshot.com/Valine快速、简洁且高效的无后端评论系统https://valine.js.org/cnpm淘宝提供的一个完整 npmjs.org 镜像，你可以用此代替官方版本(只读)，同步频率目前为 10分钟 一次以保证尽量与官方服务同步https://npmmirror.com/yarn快速、可靠和安全的依赖管理https://yarnpkg.com/responsively-app一种改进的 Web 浏览器，有助于响应式 Web 开发。Web 开发人员必须拥有开发工具https://responsively.app/javascript-obfuscator功能强大的免费 JavaScript 混淆器，包含多种功能，可为源代码提供保护https://obfuscator.io/Nano ID小巧的、安全的、URL 友好的、独特的 JavaScript 字符串 唯一 ID 生成器https://zelark.github.io/nano-id-cc/spy-debugger一站式页面调试、抓包工具。远程调试任何手机浏览器页面，任何手机移动端webview（如：微信，HybridApp等）。支持HTTP/HTTPS，无需USB连接设备https://responsively.app/fuite用于查找 Web 应用程序中的内存泄漏的工具https://github.com/nolanlawson/fuiteqs查询字符串解析和字符串化库https://github.com/ljharb/qsjs-cookie用于处理 cookie 的简单、轻量级 JavaScript APIhttps://github.com/js-cookie/js-cookietinymce排名第一的可定制、可扩展和灵活的富文本编辑器https://www.tiny.cloud/html2canvas允许在用户浏览器上对网页或其部分进行“截图”https://html2canvas.hertzen.com/shepherd引导用户浏览您的应用https://shepherdjs.dev/tinykeys极小的键盘事件监听库https://jamiebuilds.github.io/tinykeys/ag-grid用于构建企业应用程序的最佳 JavaScript 数据表https://www.ag-grid.com/tui.calendar功能齐全的 JavaScript 日程表https://ui.toast.com/tui-calendarscreenfull用于跨浏览器使用 JavaScript Fullscreen API 的简单包装器https://sindresorhus.com/screenfull/Fuse.jsJavaScript 中的轻量级模糊搜索https://fusejs.io/i18next用于浏览器或任何其他 javascript 环境（例如 Node.js、Deno）的国际化框架https://www.i18ne…

Vue3 实现一个Modal 组件
type: item
date: 2023-02-01T16:12:00+08:00
description: 一、组件设计组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念（组件）来实现开发的模式现在有一个场景，点击新增与编辑都弹框出来进行填写，功能上大同小异，可能只是标题内容或者是显示的主体内容稍微不同这时候就没必要写两个组件，只需要根据传入的参数不同，组件显示不同内容即可这样，下次开发相同界面程序时就可以写更少的代码，意义着更高的开发效率，更少的 Bug 和更少的程序体积二、需求分析实现一个Modal组件，首先确定需要完成的内容：遮罩层标题内容主体内容确定和取消按钮主体内容需要灵活，所以可以是字符串，也可以是一段 html 代码特点是它们在当前vue实例之外独立存在，通常挂载于body之上除了通过引入import的形式，我们还可通过API的形式进行组件的调用还可以包括配置全局样式、国际化、与typeScript结合三、实现流程首先看看大致流程：目录结构组件内容实现 API 形式事件处理其他完善目录结构Modal组件相关的目录结构├── plugins │ └── modal │ ├── Content.tsx // 维护 Modal 的内容，用于 h 函数和 jsx 语法 │ ├── Modal.vue // 基础组件 │ ├── config.ts // 全局默认配置 │ ├── index.ts // 入口 │ ├── locale // 国际化相关 │ │ ├── index.ts │ │ └── lang │ │ ├── en-US.ts │ │ ├── zh-CN.ts │ │ └── zh-TW.ts │ └── modal.type.ts // ts类型声明相关因为 Modal 会被 app.use(Modal) 调用作为一个插件，所以都放在plugins目录下组件内容首先实现modal.vue的主体显示内容大致如下<Teleport to="body" :disabled="!isTeleport"> ✕ <Content v-if="typeof content === 'function'" :render="content" /> <slot v-else> {{ content }} </slot> ❍ {{ t("r.confirm") }} {{ t("r.cancel") }} </Teleport>最外层上通过Vue3 Teleport 内置组件进行包裹，其相当于传送门，将里面的内容传送至body之上并且从DOM结构上来看，把modal该有的内容（遮罩层、标题、内容、底部按钮）都实现了关于主体内容 <Content v-if="typeof content==='function'" :render="content" /> <slot v-else> {{content}} </slot> 可以看到根据传入content的类型不同，对应显示不同得到内容最常见的则是通过调用字符串和默认插槽的形式// 默认插槽 <Modal v-model="show" title="演示 slot"> hello world~ </Modal> // 字符串 <Modal v-model="show" title="演示 content" content="hello world~" />通过 API 形式调用Modal组件的时候，content可以使用下面两种h 函数$modal.show({ title: '演示 h 函数', content(h) { return h( 'div', { style: 'color:red;', onClick: ($event: Event) => console.log('clicked', $event.target) }, 'hello world ~' ); } });JSX$modal.show({ title: '演示 jsx 语法', content() { return ( console.log('clicked', $event.target)} > hello world ~ ); } });实现 API 形式那么组件如何实现API形式调用Modal组件呢？在Vue2中，我们可以借助Vue实例以及Vue.extend的方式获得组件实例，然后挂载到body上import Modal from './Modal.vue'; const ComponentClass = Vue.extend(Modal); const instance = new ComponentClass({ el: document.createElement("div") }); document.body.appendC…

SSH 连接
type: item
date: 2022-11-10T15:35:00+08:00
description: 设置 Git 用户先在终端执行一下 git config --global --list，看看当前设备的 git 有没有设置好相关的用户名跟邮箱。有的话就会正常显示user.name=Your Name user.email=your-name@example.com如果没有的话，就会出现类似这种错误fatal: unable to **read** config **file** **'\~/.gitconfig'**: No such **file** or directory既然没有那就设置一下git config --global user.name "Your Name" git config --global user.email "Your Email"设置完成后要想确认一下，就重新执行git config --global --list生成 SSH Key这个就比较容易，直接执行这条命令，主要是设置一下邮箱地址ssh-keygen -t rsa -C "your-email-address"一路回车就行，一般会显示下面这些内容，具体内容以自己的系统为准Generating public/private rsa key pair. Enter file in which to save the key (~/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in ~/.ssh/id_rsa. Your public key has been saved in ~/.ssh/id_rsa.pub. The key fingerprint is: SHA256:IuTZyVphdJVuRBBYBjCYtCTD1rJcgumXe0oXdErnUeo limitliu@qq.com The key's randomart image is: +---[RSA 2048]----+ |=o+oo.o+B*o. | |oOo+ =.*. o | |+ * = B..o | | + = B.+ o | | . = BES. | | o * . | | . = | | . | | | +----[SHA256]-----+生成后把内容拷贝到自己的剪贴板，public key 文件生成在哪可以看上面执行后的结果，里面有对应文件路径，我这里生成得文件是在 ~/.ssh/id_rsa.pub 这个路径，Mac 可以直接这样执行这条命令来复制生成后把内容拷贝到自己的剪贴板，public key 文件生成在哪可以看上面执行后的结果，里面有对应文件路径，我这里生成得文件是在 `~/.ssh/id_rsa.pub` 这个路径，**Mac** 可以直接这样执行这条命令来复制之后就可以在需要使用的地方直接粘贴了

docker 简单入门。
type: item
date: 2022-08-25T02:07:00+08:00
description: 1. 通过 uname -r 查看当前的内核系统版本uname -r2. 使用root权限登录Centos. 确保yum包更新到最新yum -y update3. 卸载旧版本(如果有安装过旧版本的话)sudo yum remove -y docker*4. 安装需要的软件包 yum-util 提供yum-config-manager功能, 另外两个是devicemapper的驱动依赖yum install -y yum-utils5. 设置yum源 更新 yum的包索引yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo yum makecache fast6. 可以查看所有仓库中所有docker版本,并选择特定版本安装yum list docker-ce --showduplicates | sort -r7. 安装dockeryum install -y docker-ce-3:19.03.9-3.el7.x86_648. 启动并加入开机启动systemctl start docker && systemctl enable docker9. 验证安装是否成功docker --version10. 查看docker 本地镜像仓库docker images11.拉取远程镜像仓库内容docker pull nginx //比如nginx 默认最新 latest 版本 docker pull nginx:1.23.2-perl //选择版本拉取12. 查看本机运行的所有容器docker ps13 docker容器运行// -d 表示后台运行docker -p ==> port // 80 nginx 默认 90数组机映射端口 docker run -d -p 90:80 nginx docker run -d -p 90:80 nginx:1.23.2-perl //如果有版本14. 进入到docker容器内/退出容器docker exec -it 3ce35d262dac /bin/bash // 3ce35d262dac ==> 唯一 CONTAINER ID 通过 docker ps 查看 cd /usr/share/nginx exit // 退出15.查看容器ipdocker inspect 3ce35d262dac // 3ce35d262dac ==> 唯一 CONTAINER ID 通过 docker ps 查看 "IPAddress": "172.17.0.2", curl 172.17.0.2 //查看16.查看容器运行日志docker logs 3ce35d262dac -f17.停止容器docker stop 3ce35d262dac // 停止 docker kill 3ce35d262dac // 强制停止 docker start 3ce35d262dac // 启动已停止的容器18 容器与宿主机相互复制文件从容器里面拷贝文件到宿主机docker cp 容器id:要拷贝的问价你在容器里面的路径 宿主机的相应路径 如: docker cp 3ce35d262dac:/etc/nginx/nginx.conf /mydata/nginx从宿主机拷文件到容器里面docker cp 宿主机的相应路径 容器id:要拷贝的问价你在容器里面的路径19.DockerFile常用指令命令用途FROM基础镜像文件RUN构建镜像阶段执行的命令ADD 添加文件,从src目录复制文件到容器的dest, 其中src可以是Dockerfile所在目录的相对路径,也可以是一个URL,还可以是一个压缩包COPY拷贝文件,和ADD命令类似,但不支持URL和压缩包CMD容器启动后执行命令EXPOSE声明容器在运行时对外提供的服务端口WORKDIR指定的工作路径ENV指定的环境变量ENTRYPOINT容器入口 ENTRYPOINT 和CMD 指令的目的一样,都是指定Docker 容器启动时执行的命令,可以执行多次,但只有最后一次有效USER该指令用于设置启动镜像时的用户或者UID,写在该指令后的RUN CMD 以及 ENTRYPOINT 指令都将使用该用户执行命令VOLUME指定挂载点,该指令使容器中的一个目录具有持久化存储的功能,该目录可被本身使用,也可共享给其他容器. 当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令. 格式为: VOLUME["/data"]20. docker 打包docker build --platform linux/amd64 -f ./Docker/…

vue权限管理之控制到按钮级别的权限
type: item
date: 2022-05-20T14:03:00+08:00
description: 一、是什么权限是对特定资源的访问许可，所谓权限控制，也就是确保用户只能访问到被分配的资源而前端权限归根结底是请求的发起权，请求的发起可能有下面两种形式触发页面加载触发页面上的按钮点击触发总的来说，所有的请求发起都触发自前端路由或视图所以我们可以从这两方面入手，对触发权限的源头进行控制，最终要实现的目标是：路由方面，用户登录后只能看到自己有权访问的导航菜单，也只能访问自己有权访问的路由地址，否则将跳转 4xx 提示页视图方面，用户只能看到自己有权浏览的内容和有权操作的控件最后再加上请求控制作为最后一道防线，路由可能配置失误，按钮可能忘了加权限，这种时候请求控制可以用来兜底，越权请求将在前端被拦截二、如何做前端权限控制可以分为四个方面：接口权限按钮权限菜单权限路由权限接口权限接口权限目前一般采用jwt的形式来验证，没有通过的话一般返回401，跳转到登录页面重新进行登录登录完拿到token，将token存起来，通过axios请求拦截器进行拦截，每次请求的时候头部携带tokenaxios.interceptors.request.use(config => { config.headers['token'] = cookie.get('token') return config }) axios.interceptors.response.use(res=>{},{response}=>{ if (response.data.code === 40099 || response.data.code === 40098) { //token过期或者错误 router.push('/login') } })路由权限控制方案一初始化即挂载全部路由，并且在路由上标记相应的权限信息，每次路由跳转前做校验const routerMap = [ { path: '/permission', component: Layout, redirect: '/permission/index', alwaysShow: true, // will always show the root menu meta: { title: 'permission', icon: 'lock', roles: ['admin', 'editor'] // you can set roles in root nav }, children: [{ path: 'page', component: () => import('@/views/permission/page'), name: 'pagePermission', meta: { title: 'pagePermission', roles: ['admin'] // or you can only set roles in sub nav } }, { path: 'directive', component: () => import('@/views/permission/directive'), name: 'directivePermission', meta: { title: 'directivePermission' // if do not set roles, means: this page does not require permission } }] }]这种方式存在以下四种缺点：加载所有的路由，如果路由很多，而用户并不是所有的路由都有权限访问，对性能会有影响。全局路由守卫里，每次路由跳转都要做权限判断。菜单信息写死在前端，要改个显示文字或权限信息，需要重新编译菜单跟路由耦合在一起，定义路由的时候还有添加菜单显示标题，图标之类的信息，而且路由不一定作为菜单显示，还要多加字段进行标识方案二初始化的时候先挂载不需要权限控制的路由，比如登录页，404等错误页。如果用户通过URL进行强制访问，则会直接进入404，相当于从源头上做了控制登录后，获取用户的权限信息，然后筛选有权限访问的路由，在全局路由守卫里进行调用addRoutes添加路由import router from './router' import store from './store' import { Message } from 'element-ui' import NProgress from 'nprogress' // progress bar import 'nprogress/nprogress.css'// progress bar style import { getToken } from '@/utils/auth' // getToken from cookie NProgress.configure({…