-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.json
1 lines (1 loc) · 40.3 KB
/
search.json
1
[{"title":"Cookie, Session 和 Token 的区别","url":"/2023/04/21/Cookie-Session-%E5%92%8C-Token-%E7%9A%84%E5%8C%BA%E5%88%AB/","content":"HTTP 是一个无状态协议,这意味着每次客户端和服务器之间的通信都是独立的,服务器不会记录客户端的状态。为了实现状态管理,出现了 Cookie、Session 和 Token 三种方法。\nCookieCookie 是服务器通过 Set-Cookie 请求头,将一些数据发送到客户端,客户端将这些数据保存在浏览器中,并在后续的请求中通过 Cookie 请求头自动将这些数据发送回服务器。\nCookie 具有以下特点:\n\nCookie 存储在客户端的浏览器中,因此服务器无法直接访问 Cookie 信息。\nCookie 的大小限制为 4KB,因此不适合存储大量数据。\nCookie 具有有效期,可以通过设置 Expires 或 Max-Age 字段来指定 Cookie 的过期时间。\nCookie 可以通过设置 HttpOnly 字段来防止客户端 JavaScript 代码访问 Cookie 信息。\nCookie 可以通过设置 Secure 字段来限制 Cookie 只能在 HTTPS 连接中传输。\n\n优点:\n\nCookie 存储在客户端,不会对服务器造成压力。\nCookie 可以在不支持 HTTP 认证的 Web 浏览器中实现用户认证。\n\n缺点:\n\nCookie 存储在客户端,存在被篡改和窃取的风险。\nCookie 的大小限制了存储的数据量。\nCookie 需要通过 HTTP 请求头进行传输,增加了网络流量。\n\nSessionSession 是服务器在内存中为每个客户端创建的一个数据结构,用于存储客户端的状态信息。服务器通过在 HTTP 响应头中发送一个 Session ID,将 Session ID 存储在客户端的 Cookie 中,并在后续的请求中通过 Cookie 将 Session ID 发送回服务器。服务器根据 Session ID 找到对应的 Session 数据结构,从而实现状态管理。\nSession 具有以下特点:\n\nSession 存储在服务器端,因此服务器可以访问 Session 信息。\nSession 的大小限制取决于服务器的内存大小。\nSession 具有有效期,可以通过设置超时时间来指定 Session 的过期时间。\nSession 可以通过设置安全密钥来防止 Session 信息被篡改。\n\n优点:\n\nSession 存储在服务器端,安全性较高。\nSession 没有大小限制,可以存储大量数据。\n\n缺点:\n\nSession 存储在服务器端,对服务器造成压力。\nSession 需要通过 Cookie 进行传输,存在被窃取的风险。\nSession 需要通过 HTTP 请求头进行传输,增加了网络流量。\n\nTokenToken 是一种基于安全令牌的身份验证和授权机制。服务器在验证客户端的身份后,生成一个包含用户信息和权限的令牌,并将令牌发送给客户端。客户端将令牌保存在本地,并在后续的请求中将令牌发送回服务器。服务器根据令牌验证客户端的身份和权限。\nToken 具有以下特点:\n\nToken 存储在客户端,因此服务器无法直接访问 Token 信息。\nToken 的大小限制取决于令牌的格式和内容。\nToken 具有有效期,可以通过设置超时时间来指定 Token 的过期时间。\nToken 可以通过加密算法来防止 Token 信息被篡改。\n\n优点:\n\nToken 存储在客户端,不会对服务器造成压力。\nToken 没有大小限制,可以存储大量数据。\nToken 可以通过加密算法来提高安全性。\n\n缺点:\n\nToken 存储在客户端,存在被窃取的风险。\nToken 需要通过网络传输,增加了网络流量。\nToken 需要实现自己的身份验证和授权机制,增加了开发难度。\n\n","tags":["http"]},{"title":"【转载】Hexo 自动部署","url":"/2023/03/09/Hexo-%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2/","content":"我们搭建个人博客的初衷,不就是为了能好好地写文章吗?一切重复且枯燥的工作都应该交给程序去自动完成,尤其是静态博客编译和部署,我们只需要专注文字。\n什么是 GitHub ActionsGitHub Actions 是 GitHub 的持续集成服务。持续集成由很多操作组成,比如抓取代码、运行测试、登录远程服务器,发布到第三方服务等等。GitHub 把这些操作就称为 actions。\n很多操作在不同项目里面是类似的,完全可以共享。GitHub 允许开发者把每个操作写成独立的脚本文件,存放到代码仓库,使得其他开发者可以引用。\n如果你需要某个 action,不必自己写复杂的脚本,直接引用他人写好的 action 即可,整个持续集成过程,就变成了一个 actions 的组合。这就是 GitHub Actions 最特别的地方。\n\n本例就使用由 theme-keep 提供的 action hexo-deploy-github-pages-action 来自动部署 Hexo。\n\n使用 GitHub Actions 自动部署的好处\n可以直接在线编辑 md 文件,立即生效。假设你已发布一篇文章,过几天你在别的电脑上浏览发现有几个明显的错别字,这是完全不能容忍的。但此时你电脑上又没有 hexo + node.js + git 等完整的开发环境,重新配置开发环境明显不现实。如果使用 CI,你可以直接用浏览器访问 GitHub 上的项目仓库,直接编辑带错别字的 md 文章,改完,在线提交,稍等片刻,你的网站就自动更新了。\n如果手动部署,需要先执行 hexo g 编译生成静态文件, 然后推送 public 整个文件夹到 GitHub 上,当后期网站文章、图片较多时候,很多时候连接 GitHub 不是那么顺畅,经常要傻等很长的上传时间。使用 GitHub Actions 自动部署,你只需 push _post 文件里单独的 md 文件即可,其他不用管,效率瞬间高了许多,其中的好处,谁用谁知道。\n使用 GitHub Actions,你还可以一次性将这些静态博客页面部署到多个服务器上,例如:GitHub Pages、Gitee pages、七牛云、阿里云、腾讯云等等。\n…\n\n准备工作本文以 Hexo + Keep 主题搭建博客为例,教你如何使用 GitHub Actions 将博客自动部署到 GitHub Pages。\n创建 GitHub 仓库创建两个 GitHub 仓库,一个公共仓库和一个私有仓库。\n\n私有仓库用来存储 Hexo 项目源代码。(保证你的重要信息不泄露)\n \n\n公共仓库用来存储编译之后的静态页面。\n \n\n\n本例:\n\n用私有仓库的 master 分支来存储项目源代码。\n用公共仓库的 gh-pages 分支 来存储静态页面。\n\n当私有仓库的 master 有内容 push 进来时(例如:主题文件,文章 md 文件、图片等), 会触发 GitHub Actions 自动编译并部署到公共仓库的 gh-pages 分支。\n创建 GitHub Token创建一个有 repo 和 workflow 权限的 GitHub Token 。\n\n新生成的 Token 只会显示一次,如有遗失,重新生成即可。\n\n创建 repository secret将上面生成的 Token 添加到私有仓库的 Secrets 里,并将这个新增的 secret 命名为 HEXO_DEPLOY (名字无所谓,看你喜欢)。\n步骤:私有仓库 -> settings -> Secrets -> New repository secret。\n\n\n新创建的 secret HEXO_DEPLOY 在 Actions 配置文件要用到,需跟配置文件保持一致!\n\n添加 Actions 配置文件\n在你的 Hexo 项目根目录下创建 .github 文件夹。\n在 .github 文件夹下创建 workflows 文件夹。\n在 workflows 文件夹下创建 hexo-deploy.yml 文件。\n\n\nhexo-deploy.yml 文件的内容如下:\nname: deploying Hexo project to GitHub pageson: push: branches: - master # master 分支有 push 行为时就触发这个 actionjobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@master - name: Build and Deploy uses: theme-keep/hexo-deploy-github-pages-action@master # 使用专门部署 Hexo 到 GitHub pages 的 action env: PERSONAL_TOKEN: ${{ secrets.HEXO_DEPLOY }} # secret 名 PUBLISH_REPOSITORY: XPoet/keep-blog # 公共仓库,格式:GitHub 用户名/仓库名 BRANCH: gh-pages # 分支,填 gh-pages 就行 PUBLISH_DIR: ./public # 部署 public 目录下的文件\n\n\n在上面的配置文件中,使用了 theme-keep 组织封装的 hexo-deploy-github-pages-action ,是一款专门部署 Hexo 博客到 GitHub pages 的 action,欢迎大家 Star 和 Fork\n\n至此,准备工作完毕~\n自动部署触发流程\n修改你的 Hexo 博客源代码(例如:增加文章、修改文章、更改主题、修改主题配置文件等等)。\n\n把你修改过的 Hexo 项目内容(只提交修改过的那部分内容) push 到 GitHub 私有仓库(本例:keep-site-source)的 master 分支。\n\nGitHub Actions 检测到 master 分支有内容 push 进来,会自动执行 action 配置文件的命令,将 Hexo 项目编译成静态页面,然后部署到公共仓库的 gh-pages 分支。\n\ngh-pages 分支是 GitHub Pages 服务的固定分支,你只需在 hexo-deploy.yml 文件正确填写,会自动创建。\n\n\n在私有仓库的 Actions 可以查看到你配置的 action。 \n\n通过 GitHub Actions 自动部署成功的效果图: \n\n\n类似工具除了 GitHub Actions,我们还可以使用 Travis CI 来实现 Hexo 自动部署,效果是一样的,任君选择。\n教程:使用 Travis CI 自动部署 Hexo 静态博客\n\n作者:XPoet链接:https://juejin.cn/post/6943895271751286821来源:稀土掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。\n\n","tags":["Hexo"]},{"title":"VS Code 常用插件","url":"/2024/07/20/VS-Code-%E5%B8%B8%E7%94%A8%E6%8F%92%E4%BB%B6/","content":"界面美化Chinese (Simplified) (简体中文) Language Pack for Visual Studio Code\nAtom One Dark Theme\nMaterial Icon Theme\n工具GitLens — Git supercharged\n在源代码管理中查看 COOMITS、BRANCH、TAGS 等 GIT 仓库信息,行内显示提交缩略信息\nCodeSnap\n代码截图美化工具,选中代码后,右键选择 CodeSnap 即可打开 CodeSnap窗口,Ctrl + c 保存截图\nProject Manager\n会在侧边栏添加 Project Manger 栏,可在其中添加当前仓库,方便进行多仓库管理(当前窗口打开或新窗口打开)\n前端开发Vue - Official\n提供 Vue 项目的代码高亮\nESLint\nPrettier - Code formatter\nError Lens\n行内显示报错信息\nAuto Rename Tag\n虽然 VS Code 内部做了支持但默认不开启,需要在设置中搜索 Linked Editing 手动开启,此外 jsx 中不支持,为了方便推荐安装。\n\nTurbo Console Log\n\n添加日志 Ctrl + Alt + L\n注释所有插件添加的日志 Shift + Alt + C\n取消注释所有插件添加的日志 Shift + Alt + U\n删除所有插件添加的日志 Shift + Alt + D\n\nJavaScript (ES6) code snippets\nVue VSCode Snippets\n","tags":["手册"]},{"title":"【转载】Rust 大佬给初学者的学习建议","url":"/2023/03/15/rust-learn/","content":"简介当我开始学习 Rust 的时候,我犯了一个错误,那就是先读《The Rust Programming Language》。虽然这是一本非常好的资料,但让新手一开始就阅读这本 20 个章节的书籍,简直令人望而生畏,大多数人还没开始就放弃了。没有人会让一个刚开始学习 JavaScript 或者 Python 的人去阅读一本 20 个章节的书籍。Rust 学习曲线非常陡峭的,但只要循序渐进的学习一定也能学有所成。\n摘要如果你是一个完完全全的 Rust 小白,想要在一天中尽可能多的学习 Rust,那我推荐你去阅读 fasterthanlime 的《半小时快速了解 Rust》,然后完成 Rustlings 项目中的练习。\n如果你已经学过 Rust 的基本语法,你可以试着做一下 Exercism.io 网站上的 Rust 部分。如果你遇到了问题,你可以在 Google 或者 StackOverflow 上寻求帮助。我推荐你花点时间来简单的阅读和浏览一下《Rust Standard Library Docs》,它是一个很棒的学习资料,里面有一些简单且实用例子去帮助你更好的使用 Rust 的标准库。《Rust by Example》也是一本高质量的参考资料,你可以通过他快速的学习 Rust 的语法和特性。如果你想要更深入的理解 Rust 的某一个概念,那么我推荐你在《The Rust Programming Language》这本书中寻找相关的章节去阅读。尤其推荐在 Exercism.io 上进行练习。在完成每个题目之后,你可以查看其他所有人的题解,可以按点赞数排序来找到通俗易懂并且巧妙的题解。这是一种很棒的学习方式。\n此时,你可能已经是一个高级的初学者,能够找到属于自己的学习路线。但,如果你还需要更多的指导并想要尝试用 Rust 来写一些简单的程序,我推荐你试一着做一下 Advent of Code 2018 Calendar 上的练习。为什么推荐你做 2018 年的题目呢?因为当你做完了这个练习,你可以和 BurntSushi 提供的答案( BurntSushi’s Advent of Code 2018 Rust solutions)进行对比。BurntSushi 写的 Rust 代码整洁、可读性强、通俗易懂。阅读一个有经验的 Rustacean 的代码将会使你受益无穷。\n现在可以退出了,文章最精彩的部分已经结束了。\nRust 练习场评测别名:适合 Rust 新人的免费练习场评测\n大多数的练习场都不是专门用于练习 Rust 的,但都可以用于学习和练习 Rust。某些练习场还明确的表示可以提交 Rust 代码,并支持指定 Rust 版本。\n下面的练习场是按照从最坏到最好进行排序的。\nHackerRank虽然 HackerRank 支持 Rust 语言,但大多数题目并不能提交题解。当我上传题解的时候被直接拒绝了。\n\n迷惑。我能浏览其他用户上传的 Rust 题解,按道理说,我也可以上传 Rust 题解。我尝试在 Google 上搜索这个问题,并没有找到有用的信息。我没办法将 HackerRank 和其他网站对比,因此我只想告诉你,别像我这样浪费时间,试试其他网站吧。\n欧拉计划(Project Euler)我是从 2012 年开始学习编程的,当时我常常听到“如果你想要快速学习一门编程语言,来做几个 Project Euler 的题目吧!”,这在当时是个不错的建议,因为当时没有其他更好的选择。但在我看来,Project Euler 和编程关系不大。Project Euler 的题目大多是数学问题,而不是编程问题。这些题目需要大量的数学推导才能做出来,相比之下,所需要的编程能力是微不足道的。我不推荐你在 Project Euler 上学习 Rust,除非你数学很强或对这个网站有一些情结。\n力扣(LeetCode)力扣上支持使用 Rust 来编写题解。力扣上的每个题目,你都会得到一个模板,模板通常包含一个没有被实现函数,你需要实现它并使其完成题目要求的功能。对于某个比较复杂的问题,模板可能会包含一些 struct 结构体和 impl 代码块、几个未被实现的方法。不幸的是,这些模板不是由人工撰写的,而是由机器自动生成的,这会导致你写出许多不规范 Rust 代码。让我们来对比一下力扣生成的 Rust 代码和优雅的 Rust 代码\n\n\n\n力扣生成的 Rust 代码\n优雅的 Rust 代码\n\n\n\n使用 Option<Rc<RefCell<Node>>> 来表示链表\n使用 Option<Rc<RefCell<Node>>> 来表示链表太复杂。Option<Box<Node>> 同样能表示链表,并且使用起来更简单。\n\n\ninsert 方法需要改变 self,但生成的代码依然使用不可改变的借用。例如:fn insert(&self, val: i32)\n将 self 需要改成可变借用。例如:fn insert(&mut self, val: i32)\n\n\n即使程序不会使用负数,依然将所有的数字都声明为 32 位的整型。例如:fn nth_fib(n: i32) -> i32\n如果程序不使用负数,我们应该使用无符号整数。例如:fn nth_fib(n: u32) -> u32\n\n\n即使不需要获得参数的所有权,依然,。例如:fn sum(nums: Vec<i32>) -> i32\n如果不需要参数的所有权,那么应该使用借用。例如:fn sum(nums: &[i32]) -> i32\n\n\n在力扣上练习 Rust 的问题:\n\n力扣不允许你在做题时引入第三方的依赖。对于大多数语言来说,我认为这是合理的,但 Rust 的标准库非常小,甚至不支持正则表达式,使用 Rust 来做复杂字符串解析意义不大。由于其他语言的标准库自带正则表达式,所以做起来很简单。\n所有的并发类问题,都不能提交题解。无法理解!安全且高效的并发是 Rust 的一大亮点。\n在做完题目后,你能在问题的评论区查看其他用户的题解(许多用户喜欢讲题解发布在评论区),但由于 Rust 太小众,有时你会找不到 Rust 的题解。\n\n力扣的常见问题:\n\n力扣上有大量低质量的题目。虽然用户可以选择喜欢或是不喜欢,但题目不会被删除,即使这个题目被绝大多数讨厌。我看过许多 100+ 投票的问题,其中 80% 都是不喜欢,我不理解为什么还要保留这些题目。\n题目的难度等级不准确。力扣上的题目共有三个难度等级,分别是简单、中等、困难,但有很多简单题的解题率比难题更低。\n不是所有的题目都能用任意语言提交。你没办法直观的判断题目支持哪些语言。例如,所有关于图的题目都不支持使用 Rust 提交。\n\n力扣的优点:\n\n提交的题解会使用一组未知的数据来进行测试,如果程序在某个特殊数据出错了,它会把这个特殊数据显示给你,帮助你完善题解。\n生成的所有 Rust 代码都符合 rustfmt 格式规范。\n\nCodeWarsCodewars 这个名字经常被误解,这里并没有竞赛。Codewar 的题目没有时间限制,也不会用你的执行速度和内存使用情况来评价你的题解。值得注意的是,没有任何人和你一决高下并不是什么坏事。\nCodewars 支持使用 Rust 来编写题解。类似力扣,Codewars 上的每个题目,你都会得到一个模板,模板通常会包含一个没有被实现函数,你需要实现它并使其完成题目要求的功能。这些模板是由人工撰写的,不是所有撰写模板的人都擅长 Rust,所以你可能偶然会碰到糟糕的 Rust 题目。例如:\n\n\n\nCodewars 的模板\n优雅的 Rust 代码\n\n\n\n有时不遵循 rustfmt 格式规范,例如:fn makeUppercase(s:&str)->String\n应该尽量遵循 rustfmt 格式规范的写法,例如:fn make_uppercase(s:&str)->String\n\n\n即使程序不会使用负数,依然将所有的数字都声明为 32 位的整型。例如:fn nth_fib(n: i32) -> i32\n如果程序没有负数,我们应该使用无符号整数。例如:fn nth_fib(n: u32) -> u32\n\n\n当程序需要将 -1 作为返回结果时,例如:fn get_index(needle:i32, haystack: &[i32])->i32\n应该将返回类型包装成 Option 类型。 例如:fn get_index(needle:i32, haystack: &[i32]) -> Option<usize>\n\n\n有时不充分利用解引用强制转换。例如:fn do_stuff(s: &String, list: &Vec<i32>)\n充分利用解引用强制转换。例如:fn do_stuff(s: &str, list: &[i32])\n\n\n上面的问题只是偶然会碰到,因为撰写模板的人的技能水品不同。相比于力扣,这是一个很大的进步,力扣上的 Rust 题目普遍都比较糟糕。在 Codewars 上的 Rust 学习者整体趋向于经验不足,因为我经常在高赞题解中看见非常普通的代码。例如:\n\n\n\nCodewars 的高赞题解\n优雅的 Rust 写法\n\n\n\n有时在函数末尾使用 return。例如:return result;\n代码块可以被作为表达式,函数末尾的 return 通常省略不写。例如:result\n\n\n总是使用紧凑的格式来让题解显得更简洁。\n应该遵循 rustfmt 格式规范\n\n\n有时调用不必要的函数。例如:str_slice.to_string().chars()\n如果不需要,就不调用。例如:str_slice.chars()\n\n\n总是使用迭代器来编写题解,忽视了其他方面的问题。\n迭代器很好用,也很常用。但如果你把 15 个迭代器写在一行,或是将迭代器多层嵌套在一起,你应该考虑重构一些函数。\n\n\n上面的问题也只是偶然会碰到。有经验的 Rust 开发者能很轻松的发现这些问题,但大部分的 Rust 初学者并不清楚它们正在学习不规范的代码。\nCodewars 在 Rust 方面的其他问题:\n\nRust 的题目非常少。这个网站一共 9000 多个题目,但只有 300 个支持使用 Rust 提交题解。\n\nCodewars 的常见问题:\n\n当题目提交后,系统会使用一组未知的数据来测试你的题解。如果测试没有全部通过,系统并不会告诉你哪个数据出现问题。如果边界值没有在题目描述中清楚的交代,这会让人非常恼火。\n\nCodewars 的优点:\n\nCodewars 有一个很小的 Rust 第三方依赖库列表,你可以用这些依赖库来解决问题。支持的第三方依赖库有:rand、chrono、regex、serde、itertools、lazy_static,它们能让 Rust 更接近其他语言。\n你可以直接筛选出支持 Rust 的语言。\n题解被提交后,会被自动发布到答案区。你也可以查看其他人的题解,并对其进行投票。你可以按点赞数对题解进行排序,前面的题解通常都是简单而高效的,但有时也会不符合规范。\n题目的难度等级非常准确。Codewars 并不是像力扣一样将问题从易到难分为三个阶段(简单、中等、困难),而是将难度分为八个等级,它们由易到难分别是:8kyu、7kyu、6kyu、5kyu、4kyu、3kyu、2kyu、1kyu。在 8kyu 到 4 kyu 之间,我共计完成了 60 个题目,每一层难度都比只上一层难一点,非常适合训练。\n\nAdvent of CodeAdvent of Code(简称 AoC) 和编程语言完全没有关系。HackerRank、LeetCode、CodeWars 对 Rust 的支持并不好,相比之下,使用 AoC 可能效果更好。 在我在看,AoC 的题目是有趣的、多样化的、高质量的。\nAoC 的常见问题:\n\n当你完成练习后,没办法看到其他人的题解,并且无法判断在 Google 上搜索的题解质量。\n\n为了解决上面的问题,我推荐去做 2018 年的题目,然后将你的题解和 BurntSushi 提供的答案( BurntSushi’s Advent of Code 2018 Rust solutions)进行对比。BurntSushi 写的 Rust 代码整洁、可读性强、通俗易懂。如果你想要完成 2019 年的题目,我推荐参考 bcmyers 的题解(bcmyers’ AoC 2019 Rust solutions),bcmyers 还在 Youtube 上制作了一个 Youtube 播放列表来讲解这些题目,他很好的解释了他的思考过程以及他为什么的代码要做这些事情。\nRustlings极力推荐 Rustlings,因为它太棒了。这是一套能教会你 Rust 常规用法的练习。\n如果你是一个完完全全的 Rust 小白,你必须试试 Rustlings。不过,我极力推荐你先阅读 fasterthanlime 的《半小时快速了解 Rust》,它会帮助你迅速了解很多的 Rust 语法和概念。\nRustlings 的一点小缺陷:在“错误处理”(Error handling)和“类型转换”(Type conversions)部分突然难度飙升,很多人在这不知所措。\nRustlings 太短了,这并不是在批评它,Rustlings 设计的目的就是简单快速的介绍 Rust。但它写得太好了,我希望这样的内容能再多一点。\nExercismExercism 有一套 Rust 的练习集,大致按主题和难度系数进行排序。虽然这套 Rust 的练习集类似于其他练习集,但所有的练习题都是由经验丰富的 Rustacean 来改写的,不会遇到在 LeetCode 或 Codewars 上的问题。上面由很多 Rust 的经典问题,实现一个标准库中的 Trait,或是写一个 Macro,或是使用多线程写一个并发问题,或是使用 unsafe 编写 Rust 代码。Exercism 是仅次于 Rustlings 的 Rust 学习资料。Rustlings 被放在 Exercism 之上,仅仅是因为 Rustlings 可以在一个晚上完成,而Exercism 的 Rust 练习集需要花费至少一个月。\n在 Exercism 上练习 Rust 的问题:\n\n不能使用“指导模式”(Mentored mode)。因为网站上大部分的 Rust 导师都并不活跃,所以最好使用“练习模式”(Practice mode)\n一共有 92 个练习题,但其中很大一部分不会教你任何新知识,从中砍掉 20 个左右的练习题,可以让内容更紧凑一点。\n\nExercism 的优点:\n\n所有的练习题都是由经验丰富的 Rustacean 来改写的。\n内容包括 Rust 的习惯用法、设计模式、语言特性。\n由易到难,难度等级准确。\n你可以在题解中引用任何第三方依赖库。\n所有的测试案例都是公开的,如果测试样例不通过,你可以知道为什么没有通过。\n提交题解之后,你可以查看别人的题解,并且题解可以按质量来排序。\n\n结论同[摘要部分](https://github.com/rustlang-cn/Rustt/blob/main/Articles/[2022-04-02] Rust 大佬给初学者的学习建议.md#摘要)。\n讨论可以在下面这些地方讨论本文:\n\nlearnrust subreddit\nofficial Rust users forum\nTwitter\nrust subreddit\nHackernews\nGithub\n\n通知通过这些渠道获取最新消息\n\nFollowing pretzelhammer on Twitter or\nSubscribing to this repo’s release RSS feed or\nWatching this repo’s releases (click Watch -> click Custom -> select Releases -> click Apply)\n\n延申阅读\nCommon Rust Lifetime Misconceptions\nSizedness in Rust\nTour of Rust’s Standard Library Traits\nRESTful API in Sync & Async Rust\nLearn Assembly with Entirely Too Many Brainfuck Compilers\n\n\n原文链接: https://github.com/pretzelhammer/rust-blog/blob/master/posts/learning-rust-in-2020.md翻译:Asura选题:Asura本文由 Rustt 翻译,StudyRust 荣誉推出\n\n","tags":["Rust"]},{"title":"常用功能配置手册","url":"/2023/04/25/%E5%B8%B8%E7%94%A8%E5%8A%9F%E8%83%BD%E9%85%8D%E7%BD%AE%E6%89%8B%E5%86%8C/","content":"\n本文章记录一些常用功能的配置方法,以便于快速查找和参考。\nWindows 命令行添加 Clash 代理\n打开命令提示符(CMD)或 PowerShell。\n输入 curl www.google.com 以判断当前终端是否可以访问 Google。注:不要使用 ping 命令验证\n输入以下命令以添加代理:\n\n [Environment]::SetEnvironmentVariable('http_proxy', 'http://127.0.0.1:7890', 'Machine')[Environment]::SetEnvironmentVariable('https_proxy', 'http://127.0.0.1:7890', 'Machine')\n\n\n其中,127.0.0.1 是 Clash 代理的本地地址,7890 是 Clash 代理的默认端口。\n[Environment]::SetEnvironmentVariable(name, value, scope) 该命令用于添加环境变量\n\n\n重新打开命令提示符(CMD)或 PowerShell 输入 curl www.google.com 验证代理是否生效,若出现网页 HTML 代码则代理成功。\n\nVue3 配置禁用 Vue2 的选项 API// vite.config.jsexport default defineConfig({ // 需要添加的代码 define: { __VUE_OPTION_API__: false }})\n\nVite 项目启动后自动打开浏览器// vite.config.jsexport default defineConfig({ // 需要添加的代码 server: { open: true }})","tags":["手册"]},{"title":"【转载】彻底搞懂HTTPS的加密原理","url":"/2023/04/29/%E5%BD%BB%E5%BA%95%E6%90%9E%E6%87%82HTTPS%E7%9A%84%E5%8A%A0%E5%AF%86%E5%8E%9F%E7%90%86/","content":"HTTPS(SSL/TLS)的加密机制虽然是大家都应了解的基本知识,但网上很多相关文章总会忽略一些内容,没有阐明完整的逻辑脉络,我学习它的时候也曾废了些功夫。\n对称与非对称加密、数字签名、数字证书等,在学习过程中,除了了解“它是什么”,你是否有想过“为什么是它”?我认为有必要搞清楚后者,否则你可能只是单纯地记住了被灌输的知识,而未真正理解它。\n本文以问题的形式逐步展开,一步步解开HTTPS的面纱,希望能帮助你彻底搞懂HTTPS!\n(阅读完需要花些时间,欢迎收藏、点赞~)\n为什么需要加密?因为http的内容是明文传输的,明文数据会经过中间代理服务器、路由器、wifi热点、通信服务运营商等多个物理节点,如果信息在传输过程中被劫持,传输的内容就完全暴露了。劫持者还可以篡改传输的信息且不被双方察觉,这就是中间人攻击。所以我们才需要对信息进行加密。最容易理解的就是对称加密 。\n什么是对称加密?简单说就是有一个密钥,它可以加密一段信息,也可以对加密后的信息进行解密,和我们日常生活中用的钥匙作用差不多。\n\n用对称加密可行吗?如果通信双方都各自持有同一个密钥,且没有别人知道,这两方的通信安全当然是可以被保证的(除非密钥被破解)。\n然而最大的问题就是这个密钥怎么让传输的双方知晓,同时不被别人知道。如果由服务器生成一个密钥并传输给浏览器,那在这个传输过程中密钥被别人劫持到手了怎么办?之后他就能用密钥解开双方传输的任何内容了,所以这么做当然不行。\n换种思路?试想一下,如果浏览器内部就预存了网站A的密钥,且可以确保除了浏览器和网站A,不会有任何外人知道该密钥,那理论上用对称加密是可以的,这样浏览器只要预存好世界上所有HTTPS网站的密钥就行了!这么做显然不现实。怎么办?所以我们就需要非对称加密 。\n什么是非对称加密?简单说就是有两把密钥,通常一把叫做公钥、一把叫私钥,用公钥加密的内容必须用私钥才能解开,同样,私钥加密的内容只有公钥能解开。\n\n用非对称加密可行吗?鉴于非对称加密的机制,我们可能会有这种思路:服务器先把公钥以明文方式传输给浏览器,之后浏览器向服务器传数据前都先用这个公钥加密好再传,这条数据的安全似乎可以保障了!因为只有服务器有相应的私钥能解开公钥加密的数据。\n然而反过来由服务器到浏览器的这条路怎么保障安全?如果服务器用它的私钥加密数据传给浏览器,那么浏览器用公钥可以解密它,而这个公钥是一开始通过明文传输给浏览器的,若这个公钥被中间人劫持到了,那他也能用该公钥解密服务器传来的信息了。所以目前似乎只能保证由浏览器向服务器传输数据的安全性(其实仍有漏洞,下文会说),那利用这点你能想到什么解决方案吗?\n改良的非对称加密方案,似乎可以?我们已经理解通过一组公钥私钥,可以保证单个方向传输的安全性,那用两组公钥私钥,是否就能保证双向传输都安全了?请看下面的过程:\n\n某网站服务器拥有公钥A与对应的私钥A’;浏览器拥有公钥B与对应的私钥B’。\n浏览器把公钥B明文传输给服务器。\n服务器把公钥A明文给传输浏览器。\n之后浏览器向服务器传输的内容都用公钥A加密,服务器收到后用私钥A’解密。由于只有服务器拥有私钥A’,所以能保证这条数据的安全。\n同理,服务器向浏览器传输的内容都用公钥B加密,浏览器收到后用私钥B’解密。同上也可以保证这条数据的安全。\n\n的确可以!抛开这里面仍有的漏洞不谈(下文会讲),HTTPS的加密却没使用这种方案,为什么?很重要的原因是非对称加密算法非常耗时,而对称加密快很多。那我们能不能运用非对称加密的特性解决前面提到的对称加密的漏洞?\n非对称加密+对称加密?既然非对称加密耗时,那非对称加密+对称加密结合可以吗?而且得尽量减少非对称加密的次数。当然是可以的,且非对称加密、解密各只需用一次即可。请看一下这个过程:\n\n某网站拥有用于非对称加密的公钥A、私钥A’。\n浏览器向网站服务器请求,服务器把公钥A明文给传输浏览器。\n浏览器随机生成一个用于对称加密的密钥X,用公钥A加密后传给服务器。\n服务器拿到后用私钥A’解密得到密钥X。\n这样双方就都拥有密钥X了,且别人无法知道它。之后双方所有数据都通过密钥X加密解密即可。\n\n完美!HTTPS基本就是采用了这种方案。完美?还是有漏洞的。\n中间人攻击\n如果在数据传输过程中,中间人劫持到了数据,此时他的确无法得到浏览器生成的密钥X,这个密钥本身被公钥A加密了,只有服务器才有私钥A’解开它,然而中间人却完全不需要拿到私钥A’就能干坏事了。请看:\n\n某网站有用于非对称加密的公钥A、私钥A’。\n浏览器向网站服务器请求,服务器把公钥A明文给传输浏览器。\n中间人劫持到公钥A,保存下来,把数据包中的公钥A替换成自己伪造的公钥B(它当然也拥有公钥B对应的私钥B’)。\n浏览器生成一个用于对称加密的密钥X,用公钥B(浏览器无法得知公钥被替换了)加密后传给服务器。\n中间人劫持后用私钥B’解密得到密钥X,再用公钥A加密后传给服务器。\n服务器拿到后用私钥A’解密得到密钥X。\n\n这样在双方都不会发现异常的情况下,中间人通过一套“狸猫换太子”的操作,掉包了服务器传来的公钥,进而得到了密钥X。根本原因是浏览器无法确认收到的公钥是不是网站自己的,因为公钥本身是明文传输的,难道还得对公钥的传输进行加密?这似乎变成鸡生蛋、蛋生鸡的问题了。解法是什么?\n如何证明浏览器收到的公钥一定是该网站的公钥?其实所有证明的源头都是一条或多条不证自明的“公理”(可以回想一下数学上公理),由它推导出一切。比如现实生活中,若想证明某身份证号一定是小明的,可以看他身份证,而身份证是由政府作证的,这里的“公理”就是“政府机构可信”,这也是社会正常运作的前提。\n那能不能类似地有个机构充当互联网世界的“公理”呢?让它作为一切证明的源头,给网站颁发一个“身份证”?\n它就是CA机构,它是如今互联网世界正常运作的前提,而CA机构颁发的“身份证”就是数字证书。\n数字证书\n网站在使用HTTPS前,需要向CA机构申领一份数字证书,数字证书里含有证书持有者信息、公钥信息等。服务器把证书传输给浏览器,浏览器从证书里获取公钥就行了,证书就如身份证,证明“该公钥对应该网站”。而这里又有一个显而易见的问题,“证书本身的传输过程中,如何防止被篡改”?即如何证明证书本身的真实性?身份证运用了一些防伪技术,而数字证书怎么防伪呢?解决这个问题我们就接近胜利了!\n如何放防止数字证书被篡改?我们把证书原本的内容生成一份“签名”,比对证书内容和签名是否一致就能判别是否被篡改。这就是数字证书的“防伪技术”,这里的“签名”就叫数字签名:\n数字签名这部分内容建议看下图并结合后面的文字理解,图中左侧是数字签名的制作过程,右侧是验证过程:\n\n数字签名的制作过程:\n\nCA机构拥有非对称加密的私钥和公钥。\nCA机构对证书明文数据T进行hash。\n对hash后的值用私钥加密,得到数字签名S。\n\n明文和数字签名共同组成了数字证书,这样一份数字证书就可以颁发给网站了。那浏览器拿到服务器传来的数字证书后,如何验证它是不是真的?(有没有被篡改、掉包)\n浏览器验证过程:\n\n拿到证书,得到明文T,签名S。\n用CA机构的公钥对S解密(由于是浏览器信任的机构,所以浏览器保有它的公钥。详情见下文),得到S’。\n用证书里指明的hash算法对明文T进行hash得到T’。\n显然通过以上步骤,T’应当等于S‘,除非明文或签名被篡改。所以此时比较S’是否等于T’,等于则表明证书可信。\n\n为何么这样可以保证证书可信呢?我们来仔细想一下。\n中间人有可能篡改该证书吗?假设中间人篡改了证书的原文,由于他没有CA机构的私钥,所以无法得到此时加密后签名,无法相应地篡改签名。浏览器收到该证书后会发现原文和签名解密后的值不一致,则说明证书已被篡改,证书不可信,从而终止向服务器传输信息,防止信息泄露给中间人。\n既然不可能篡改,那整个证书被掉包呢?\n中间人有可能把证书掉包吗?假设有另一个网站B也拿到了CA机构认证的证书,它想劫持网站A的信息。于是它成为中间人拦截到了A传给浏览器的证书,然后替换成自己的证书,传给浏览器,之后浏览器就会错误地拿到B的证书里的公钥了,这确实会导致上文“中间人攻击”那里提到的漏洞?\n其实这并不会发生,因为证书里包含了网站A的信息,包括域名,浏览器把证书里的域名与自己请求的域名比对一下就知道有没有被掉包了。\n为什么制作数字签名时需要hash一次?我初识HTTPS的时候就有这个疑问,因为似乎那里的hash有点多余,把hash过程去掉也能保证证书没有被篡改。\n最显然的是性能问题,前面我们已经说了非对称加密效率较差,证书信息一般较长,比较耗时。而hash后得到的是固定长度的信息(比如用md5算法hash后可以得到固定的128位的值),这样加解密就快很多。\n当然也有安全上的原因,这部分内容相对深一些,感兴趣的可以看这篇解答:crypto.stackexchange.com/a/12780\n怎么证明CA机构的公钥是可信的?你们可能会发现上文中说到CA机构的公钥,我几乎一笔带过,“浏览器保有它的公钥”,这是个什么保有法?怎么证明这个公钥是否可信?\n让我们回想一下数字证书到底是干啥的?没错,为了证明某公钥是可信的,即“该公钥是否对应该网站”,那CA机构的公钥是否也可以用数字证书来证明?没错,操作系统、浏览器本身会预装一些它们信任的根证书,如果其中会有CA机构的根证书,这样就可以拿到它对应的可信公钥了。\n实际上证书之间的认证也可以不止一层,可以A信任B,B信任C,以此类推,我们把它叫做信任链或数字证书链。也就是一连串的数字证书,由根证书为起点,透过层层信任,使终端实体证书的持有者可以获得转授的信任,以证明身份。\n另外,不知你们是否遇到过网站访问不了、提示需安装证书的情况?这里安装的就是根证书。说明浏览器不认给这个网站颁发证书的机构,那么你就得手动下载安装该机构的根证书(风险自己承担XD)。安装后,你就有了它的公钥,就可以用它验证服务器发来的证书是否可信了。\n\n每次进行HTTPS请求时都必须在SSL/TLS层进行握手传输密钥吗?这也是我当时的困惑之一,显然每次请求都经历一次密钥传输过程非常耗时,那怎么达到只传输一次呢?\n服务器会为每个浏览器(或客户端软件)维护一个session ID,在TLS握手阶段传给浏览器,浏览器生成好密钥传给服务器后,服务器会把该密钥存到相应的session ID下,之后浏览器每次请求都会携带session ID,服务器会根据session ID找到相应的密钥并进行解密加密操作,这样就不必要每次重新制作、传输密钥了!\n总结可以看下这张图,梳理一下整个流程(SSL、TLS握手有一些区别,不同版本间也有区别,不过大致过程就是这样):\n\n至此,我们已自上而下地打通了HTTPS加密的整体脉络以及核心知识点,不知你是否真正搞懂了HTTPS呢?找几个时间,多看、多想、多理解几次就会越来越清晰的!那么,下面的问题你是否已经可以解答了呢?\n\n为什么要用对称加密+非对称加密?\n为什么不能只用非对称加密?\n为什么需要数字证书?\n为什么需要数字签名?…\n\n当然,由于篇幅和能力所限,一些更深入的内容没有覆盖到。但我认为一般对于前后端开发人员来说,了解到这步就够了,有兴趣的可以再深入研究~如有疏漏之处,欢迎指出。\n\n作者:顾伊凡 YGY链接:https://zhuanlan.zhihu.com/p/43789231来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。\n\n","tags":["HTTP","HTTPS","加密"]}]