提醒!
此教程仅提供大致的加密货币提现方法,用于国内优秀开源贡献者兑换奖金。参与加密货币交易违反国内政策,投资须谨慎,加密货币风险高,请不要参与炒币,场外交易有刑事风险!
$rawfile
方法加载本地 HTML 网页:1 | Web({ src: $rawfile("local.html"), controller: this.webviewController }) |
但是如果在 local.html 中需要引用一些静态资源,例如图片、JS、CSS 等,静态资源放在 local.html 同级目录下,会出现跨域的错误:
1 | Access to ... at 'resource://...' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, arkweb, data, chrome-extension, chrome, https, chrome-untrusted. |
这是因为本地资源的 URL 是以 resource://
开头的,Web 组件没有这种类型 URL 的跨域处理策略。
怎样解决跨域问题?我想到了一种通过 onInterceptRequest
拦截请求解决跨域的方法,在此分享,该方法 不一定是最佳实践,但确实能够解决跨域。
1 | import url from '@ohos.url'; |
如果跨域是因为 H5 需要向服务器请求获取数据,不是加载本地资源文件导致的,可以把上面代码中的 localMockUrl
改成和服务器相同的 origin(例如 http://api.xxx.com
,结尾不要带 /
),实现本地资源和服务器资源同域,并在 onInterceptRequest
中补充下面的判断:
1 | // 把这个判断改成你实际判断服务端请求的方式 |
效果:
还不明白的可以拉这个仓库自己试验: https://gitee.com/imaegoo/hm-cors-demo
代码在 entry/src/main/ets/pages/Index.ets
和 entry/src/main/resources/rawfile/local.html
里
第一种方式比较复杂,涉及到 PDF.js 资源的加载、跨域的处理等,我就直接放代码仓库,读者可以自行研究: https://gitee.com/imaegoo/hm-pdf-viewer
更加推荐第二种方式,写法更简单
1 | import web_webview from '@ohos.web.webview'; |
第三种方式需要写 C++,暂时没找到现成的类库,所以没有走这条路
]]>前天 Tianli 提醒我,Starknet 正在向给 Github 按 star 排前 5000 个 repo 贡献过代码的人发钱,可以领领看。仔细研究了一下,最终我也拿到了这笔意外之财。
下面分享一下过程。
首先看一下领取条件
在 2023 年 11 月 15 日之前,您至少向全球星数排名前 5,000 位的版本库提交了三次内容。其中至少一次提交发生在 2018 年或之后。
即使不符合条件也先不要气馁,可以试着查一下资格,因为这 5000 个仓库的范围比较迷,我甚至都不记得自己是给哪个仓库贡献达标的……
打开 provisions.starknet.io,点击 Eligibility check only,选择 GitHub,输入 GitHub 用户名,点击 Go,如果提示 Congratulations,那你就可以领到这笔钱了。
接着点击 Disconnect,点 Claim STRK,按步骤下载浏览器插件(选哪个都可以,我选择的是 Argent X),创建一个钱包地址,在核验资格的步骤选择最后一个 GitHub,授权 GitHub 账号,然后这笔钱就到自己的钱包里了,不知道各位都领了多少,我领到了 111.1。大约 1~2 分钟检查钱包到账情况。
接下来提现到支付宝。由于我国的加密货币政策原因,提现一定要选择安全正规的大平台进行,提现的大致过程如下
感谢那些一直默默付出的贡献者们,这次空投给开源社区打了一剂振奋剂,也引来了不少别出心裁之人……
还有一些开源项目表示自己收到了许多垃圾 PR,或许是一些人希望借此抢下一次的空投。
]]>鸿蒙系统将移除 AOSP(Android 开源项目),不再兼容 apk 格式的安卓应用的安装。
系统 | Harmony | Android |
---|---|---|
语言 | ArkTS | Java |
IDE | DevEco Studio | Android Studio |
安装包格式 | APP | APK |
API 9 对应兼容安卓的鸿蒙,API 10 和 API 11 对应鸿蒙 NEXT。
鸿蒙 NEXT 的开发套件目前是内测状态,不过个人开发者也可以申请,申请地址是: https://developer.harmonyos.com/deveco-developer-suite/enabling/kit?currentPage=1&pageSize=100
鸿蒙 NEXT 的文档地址: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/environment_config-0000001052902427-V2
个人申请到开发套件后,鸿蒙 NEXT 的文档仍然没法看,想看文档需要企业开发者账号。只能先看着 API 9 的文档。
不想申请也没关系,可以先用已经成熟的 API 9 开发自己的 APP,待到 API 10 发布之后,再升级。应用模型推荐用 Stage 模型,FA 模型正在逐渐被淘汰。
需要预先装好 Node.js 16(NEXT 是 18),最好不要同时装好几个版本的 Node.js,也不要同时装正式版的 IDE 和内测版的 IDE,否则 Hvigor(构建工具)会出现奇妙的问题……
可以用模拟器开发。但模拟器有不少坑,诸如卡顿、文件管理器调不起来、WebView 无法滚动等。如果真心想钻研鸿蒙开发,建议买台华为手机。
许多人比较关心,一个 APP,我 iOS 用 Swift 开发一遍,Android 用 Java 开发一遍,鸿蒙还要再用 ArkTS 再开发一遍?将来万一再出个小米澎湃 OS 应用……
对此鸿蒙的技术人员表示,以后也会支持 React Native 和 Flutter 跨平台开发框架打包成鸿蒙应用,用这类框架的应用,鸿蒙化改造成本会很低。
1 月 18 日发公测。大概秋季正式版。
鸿蒙 NEXT 最早推送的机型有 nova 12、mate 60、mate x5,模拟器会先适配 mac arm。
据说正式版会保留一个沙箱用以运行安卓应用,和鸿蒙系统隔离开来,不知道真的假的。
]]>讯飞星火的调用文档: https://www.xfyun.cn/doc/spark/Web.html
通义千问的调用文档: https://help.aliyun.com/zh/dashscope/developer-reference/api-details
发现官方文档对于前端浏览器直接调用 API 的示例都写得不够清楚,所以在此重新封装了示例。
星火用的是 WebSocket 协议,千问用的是 Server-Sent Events,也就是 SSE。
注意:示例中直接把密钥写进了前端代码,生产环境不推荐这么做,建议通过 nginx 代理等方式将密钥注入请求。
开通服务: https://xinghuo.xfyun.cn/sparkapi
1 | import CryptoJS from "crypto-js"; |
开通服务: https://dashscope.console.aliyun.com/overview
1 | import type { ChatHistory } from "./ai"; |
1 | try { |
自适应浅色主题和深色主题,自适应内容区宽度,自适应电脑、平板、手机。
如果是在 Hexo 中使用,请将代码放到
1 | {% raw %} |
代码块中。
以下友链页样式代码都是我原创设计开发的,采用 MIT 协议开源,不适用于本站全局声明的 CC BY 4.0 协议,喜欢的朋友可以直接复制,无需署名。
1 | <style type="text/css"> |
截至 2023-10-11,本站共有 80 条正常状态的友链,超过半数为被动交换。挨个回访耗时较长,所以多数友链并不能及时回访。在此呼吁各位站长朋友开通博客的 RSS 功能,以方便其他朋友通过阅读器爬取您的最新文章。
我是如何管理这么多友链的?
答案是用 vika 管理友链表
用 inoreader 爬取最新文章
用自己开发的脚本,从 vika api 获取友链表,生成友链页 markdown
2023 年 9 月底似乎不少博主收到了收购网站的消息,具体目的不明(有懂的可以说一下吗?)。本站也收到了类似消息。
在此说明:本站域名和网站不会出售。如果您打算出售的网站在本站的友链页中,请务必告知本站更新友链或下线友链。
]]>C:\Users\你的用户名\.ssh\config
文件(没有扩展名,如果已存在此文件则不用新建),编辑此文件增加以下内容:1 | Host github.com *.github.com |
其中 Host
右边为需要走代理的域名列表,127.0.0.1:7890
替换为自己的代理服务器地址。
1 | git config --global http.proxy "http://127.0.0.1:7890" |
其中 127.0.0.1:7890
替换为自己的代理服务器地址。
favdata
,即可筛选出收藏点的 API 接口。如果你的收藏点多于 100 个,你会筛选出多个请求。依次点击每个请求,点击 Preview,展开 sync - newdata,右键 newdata,点击 Copy object 即可复制出来收藏数据。不要去复制 Response 里的内容,里面的中文是 \uxxxx
这种转义的格式。
接下来把每个请求复制出来的 newdata 整理到一个文件当中,再写一段代码转换为 Excel 格式方便查看。
1 | const { utils, writeFile } = require("xlsx"); |
用 Node.js 跑一下,再打开生成的 百度地图收藏.xlsx 稍微整理一下格式,搞定!位置名称、地址、经纬度信息都有。
]]>new Date()
显示的时区是 GMT,进一步测试发现,只有 Kylin 桌面系统上有这个问题,统信 UOS 系统没问题,解决方法很简单,在程序启动前手动指定时区。1 | process.env.TZ = 'Asia/Shanghai'; |
1 | registry=https://registry.npmmirror.com/ |
@electron-forge/maker-squirrel
?因为这种安装包格式双击会直接安装,没有任何提示,很违背 Windows 用户的操作习惯,无法自选安装路径。另外,VSCode 的安装包也在用 Inno Setup。Inno Setup 本身并不大,我们可以对它做个二次封装,方便流水线环境调用。@electron-forge/maker-deb
,大部分 Linux 桌面系统都支持@electron-forge/maker-dmg
@electron-forge/maker-zip
1 | # CentOS |
1 | sudo yum install gcc gcc-c++ make -y |
$emit
不生效问题的解决,子组件向父组件 $emit
事件,没有报错,但父组件就是收不到事件。首先排除拼错事件名称等基本错误。最终发现原因是:由于我将 $emit
写在了异步方法里,子组件在还没 $emit
之前就销毁了,此时再调用 $emit
不会有任何报错,也不会有任何效果,特此记录。
子组件
1 | // 这是一个菜单组件,假设某个菜单项被点击 |
父组件
1 | <dropdown-menu |
解决方法有两种,一种是将父组件中的 v-if
换成 v-show
以避免子组件销毁,另一种是延迟销毁,即父组件接收到以上示例的 close 事件时先不销毁子组件,接收到 finish 时再销毁。
后记:如果 Vue 能在 “调用已销毁组件的 emit 方法” 时打印一个警告,这个问题就更容易被发现了。
]]>一开始在做个人博客的框架选型时,我考虑过 WordPress、Typecho 等 PHP 框架,它们都自带一个内容管理系统,非常便于管理。但因为不想在服务器上花太多成本,我仍然选择了 Hexo 这种静态博客生成器,因为有很多优秀的静态博客托管平台可以选择。从此开始了一段博客折腾之旅。
曾经我也向朋友推荐 Hexo,列举它的种种优点,现在我也开始觉得 Hexo 写作太繁琐了。
静态博客最主要的缺点,一是不支持评论,二是缺少一个后台。不支持评论,写好的内容,无法与读者交流,是一件挺痛苦的事情。为此我搜遍互联网,最终选择了自己开发 Twikoo 无服务器评论系统,评论这件难题算是解决了。
缺少后台,便无法专注于写作,在 IDE(集成开发环境)里写博客是个很奇妙的体验,总觉得自己写的并不是博客,而是某个程序。插入图片也是个大难题,本来一个 Ctrl + V
快捷键就能插入的图片,在静态博客里需要保存图片,重命名,移动到博客静态资源目录,复制相对路径,粘贴到 ![]()
块中……受不了了,能不能再做个无服务器的内容管理系统?理论可以,但是没那个精力啊……
以下评测的方案,都仅限于 无服务器 方案,有服务器方案不参与评测,原因很简单,我搭建静态博客就是因为它无服务器的优点,如果我有服务器,为什么不直接搭建 Typecho 呢?
试用过 ChenYFan 大佬开发的两款 Hexo 内容管理工具 HexoPlusPlus,HexoPlusPlus 停止开发之后又推出了 Wexagonal,都不算成熟,对多目录支持不够好,小问题不断,最后还是没能用起来。
再后来听说了 Headless CMS 的概念,也就是无头内容管理系统,和普通博客相比,普通博客输出 HTML 网页,无头博客输出 JSON 内容接口。博客具体长什么样就完全由前端决定了。典型代表是 Ghost,具体可以看他们的教程 Build A Custom Publication With Headless Ghost + Hexo。缺点很明显,CMS 只提供接口,我还需要自己开发插件来调用这些接口获取博客内容,这是个不小的改造,就算改造好了,万一以后 Ghost 停止运营了呢?
怎么办?静态博客就没办法做内容管理了吗?
Git-based CMS 来了,它让我直呼这就是静态博客的终极内容管理方案。
Git-based CMS 就是基于 Git 的内容管理系统,原理是通过前端直接调用诸如 GitHub 等源代码托管网站的 API 来实现内容管理,不需要自己准备服务器。常见的 Git-based CMS 有两个,一个是 decap-cms,一个是 tinacms,以下是我总结出的它们的特点。
名称 | 前身 | 特点 |
---|---|---|
Decap CMS | Netlify CMS | 拥有较多用户,界面简洁,配置难度一般,用一个 js 加一个配置文件实现,2022 年开始停止开发 |
Tina CMS | Forestry.io | 后起之秀,编辑器功能更强大,配置难度简单,用专门的中间件实现,截至目前仍在积极开发 |
我先选择了 Tina,根据官方文档一番操作集成好之后,我遇到了以下问题:
<!-- more -->
来实现摘要和正文的分离,这种语法在 Tina 编辑器中直接报错。@tinacms/cli
和 tinacms
,感觉有点重。第二、三个问题还好,第一个问题就比较烦人了,正文都编辑不了怎么玩?
再试试 Decap,虽然配置起来复杂了些。但用起来总归没出现什么问题。
虽然两家 CMS 都没有在文档中写 Hexo 的集成方案,但是和同类的静态博客框架集成是差不多的。如果 Tina 能解决 markdown 非法字符的问题,两家 CMS 都是不错的选择。这里简单总结一下 Decap 与 Hexo 的集成步骤。
重要前提:Hexo 博客源码(不是生成好的 html)托管在 GitHub、GitLab、Bitbucket、Azure 四者之一的源代码托管平台,如果你纠结于选哪个,我推荐:除 GitHub 之外,哪个你访问起来快选哪个。如果你的博客源码还在本地,那我建议你推上去再说,许多小博客停止更新的原因,都是源码找不到了。
为啥我不推荐放 GitHub?
因为 Github 的 OAuth 实现 必须要有服务器,这导致配置起来稍微麻烦那么一丢丢,也就一丢丢。如果你已经放到 GitHub 上了,也不用再迁到其他平台的。
还有一个重要前提:博客已经做好了流水线自动部署,如果没有自动部署,你的内容就只会被提交到 Git 仓库,而不会自动发表到网站上。自动部署不是本文重点,你可以看我以前的文章 给Hexo博客配置Azure CI持续集成实现自动部署,或者搜索 Hexo 自动部署,找到各种各样的教程。
Decap 虽然是 Netlify 出品,但并不强依赖 Netlify 的服务,除非你想用 Netlify Identity 做身份认证,或者用 Git Gateway 的后端模式,否则你完全可以不申请 Netlify 账号。
好了,准备好代码仓库和流水线以后,我们正式开始搭建 CMS。
修改 Hexo 配置文件 _config.yml
1 | skip_render: admin/**/* |
这代表原样输出 source/admin 目录下的文件,不经过 Hexo 的渲染器。如果不配置,后面我们放到 admin 目录下的 yml 配置文件会被 Hexo 转换成 json 文件,影响使用。
如果你的 skip_render 还配置有别的目录,比如 assets,可以这样写
_config.yml
1 skip_render: (admin|assets)/**/*
创建一个文件 source/admin/index.html
,这是内容管理系统的入口文件。
1 |
|
再创建一个文件 source/admin/config.yml
,这是内容管理系统的配置文件。
配置文件要按照自己博客的实际情况改写,以下是本博客的配置文件,仅供参考:
1 | # https://decapcms.org/docs/configuration-options/ |
有关配置文件的介绍,官方文档 已经讲得非常详细了。我再简单介绍一下配置文件的几个部分。
配置文件配好之后,我们还需要创建一个 OAuth 应用来支持 Decap 访问到我们的博客源码仓库,登录自己的博客源码托管平台,GitHub 参考这个,GitLab 参考这个,Azure 参考这个,Bitbucket 参考这个,以 Bitbucket 为例:
名称描述随意,Callback URL 填写 https://博客地址/admin/
,权限选择 Account-Read
和 Pull requests-Write
,创建好的 OAuth 应用是这样的:
把回显的 Key 填到 config.yml 的 backend.app_id
里,Secret 不用管。
然后……就没啦!部署博客,然后访问 https://博客地址/admin/
用 Bitbucket 登录,就可以愉快地进行创作了。
1 | - package.json |
1 | { |
例如 @monorepo-demo/core
要依赖 @monorepo-demo/shared
1 | { |
workspace:*
标志在发包的时候会被自动替换成对应的版本号,参考这里。
在根目录下运行 yarn workspace <workspace-name> <command>
来执行任何子项目中定义的命令。例如:
1 | yarn workspace @monorepo-demo/core dev |
这会运行 core 子项目中定义的 dev 命令。
]]>问题如图,标签栏中的“编码”二字比后面的“安全指南”要高一像素,非常难看。
搜索互联网,得到的解决方案是添加一项配置:
1 | "font_options": ["gdi"] |
或者
1 | "font_face": "中文字体", |
这似乎是针对正文区的配置,对于标签栏并不起作用,于是我继续研究,发现了以下解决方法,针对标签栏:
点击 菜单 - 设置 - 定制配色方案
加入以下配置,如果已有其他配置请自行合并
1 | { |
效果如图,舒服多了
]]>我的 Puppeteer 版本:19.4.1
>=14.1.0
1 | npm config set PUPPETEER_DOWNLOAD_HOST=https://registry.npmmirror.com/-/binary |
puppeteer.launch 指定了 Chrome 浏览器路径,启动后任务管理器进程中有 chrome.exe 但代码不往下走
必须使用 Chromium 或者 Chrome Canary(金丝雀)版本,不要使用 Chrome 正式版。
安装 Chromium 所需的运行依赖,以下是 RedHat Enterprise 需要安装的依赖。
1 | yum install -y alsa-lib.x86_64 atk.x86_64 cups-libs.x86_64 gtk3.x86_64 ipa-gothic-fonts libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXrandr.x86_64 libXScrnSaver.x86_64 libXtst.x86_64 pango.x86_64 xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-fonts-cyrillic xorg-x11-fonts-misc xorg-x11-fonts-Type1 xorg-x11-utils |
另外,有些 Linux 内核不支持 sandbox,还需要在 Chromium 启动参数里加 --no-sandbox --disable-setuid-sandbox
从 Windows 复制宋体、黑体、微软雅黑等常用字体到 Linux /usr/share/fonts/
下,然后执行
1 | yum install -y fontconfig mkfontscale |
通常是单页面应用还没有加载完就触发了导出造成的,可以通过等待页面指定元素出现再导出来解决。
1 | await browserPage.goto('http://localhost:8080', { waitUntil: 'networkidle2' }); |
容器运行 Chromium 无头浏览器推荐添加的参数
1 | const browser = await puppeteer.launch({ |
1 | console.log('Starting Chromium...'); |
总之,遇到问题时多打日志,更容易分析具体是哪一步出的问题。
]]>今日收到打赏,付款方备注:
请不要在打赏备注中提问问题……哈喽,你的虹墨空间站很棒啊!先单纯赞助下。另外想问下框架的源码方便提供吗?本人无前段经验,只想要个框架往里面添加笔记文档
由于打赏无法直接回复,也看不到联系方式,所以在此回复:感谢打赏,博客框架的源码(也就是主题?)在这里可以找到:https://github.com/imaegoo/hexo-theme-icarus,具体用法和原版 hexo-theme-icarus 基本一致,您只需要按照 Hexo 主题的起步文档,就能很快搭建一个一模一样的出来了。
以下附上本站的完整主题配置文件,供有需要的朋友参考。
1 | # Version of the configuration file |
完整的博客源码由于包含原始文章,为避免恶意的全站复制和转载,恕不会开源。
]]>Ctrl + F
。数据来源:米游社《牌手预演》小游戏。
数据整理:iMaeGoo
GitHub:https://github.com/imaegoo/genius-invokation-cards
GitHub Pages:https://gcards.imaegoo.com
]]>这家电影院环境舒适,设备先进,还是个大牌子影城。但因为是一家新开的电影院,生意并不怎么好。
电影院为你这样的第一批访客送出一张会员卡,有效期五年内,每个月都可以免费观看两场电影。
你十分高兴,不仅给电影院提出了一些改进建议,还推荐了许多身边的人前来观看。
于是,电影院的生意越来越好,后来的人虽然没有能免费观影的会员卡,但也能以特惠价看到不错的电影。
两年过去了,突然有一天——
电影院宣布会员制升级,取消特惠价,而你需要支付三倍于以往会员的价格,成为新会员,如果不升级,你的老会员卡也会跟着作废。
你前去质问电影院为什么没到期会员卡也要作废,电影院只吐出五个字“会员制升级”,并排出两张你没见过的用户协议。
你非常生气,没有办理新会员,从此再没去过这家电影院。
多年之后回想起这件事,你已然记不清影院的名字,只能依稀记得影院的缩写 tcb,还有个似乎已经不再使用的老域名 qcloud.com
]]>图标 | 成就名 | 获取方式 |
---|---|---|
Arctic Code Vault Contributor | 绝版,提交过的代码在 2020 年被 GitHub Archive Program 北极代码库收录 | |
Galaxy Brain | 回答别人的 discussion 并被评为最佳答案 | |
Pull Shark | 提交的 PR 被合并 | |
Starstruck | 个人项目获得很多星(这里我不确定具体数目,我的成就写的是 512 stars) | |
YOLO | 不评审直接合并代码,目前逻辑是自己合并自己的也算,有较大争议的成就 | |
Quickdraw | 建立 issue 并在 5 分钟之内关掉,目前逻辑是自己关闭自己的也算 | |
Pair Extraordinaire | 创建多作者提交,发 PR,合并(关于如何创建多作者提交,请参考这篇帮助) | |
Public Sponsor | 赞助组织或用户 |
利用现有的查询和新增接口,如何在不改后端的情况下给页面增加导入和导出功能?
前端查询到数据,可以生成 xlsx 文件吗?
前端可以读取用户选择的 xlsx 文件,然后调用新增接口向后端写入数据吗?
可以!
通过 npm 安装
1 | npm install xlsx |
或者通过 CDN 引入(不推荐)
1 | <script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script> |
我安装的是 0.18.5 版本
1 | import { utils, read } from 'xlsx' |
通过以上方法得到的是一个 js Array 对象,表头会自动转化为对象键,表内容会自动转化为对象值,例如——
工号 | 姓名 |
---|---|
1000 | 张三 |
1001 | 李四 |
会被转换为——
1 | [ |
1 | import { utils, writeFile } from 'xlsx' |
与前面的导入功能正好相反,导出时对象键会自动转化为表头,对象值会自动转化为表内容——
1 | [ |
会被转换为——
id | name |
---|---|
1000 | 张三 |
1001 | 李四 |
为了规范导出的表头,建议先通过 map 方法生成好导出对象结构,再调用导出方法——
1 | /** |
有意思的是,xlsx.writeFile
方法同时支持 node.js 和浏览器环境,在 node.js 环境运行会将文件写入当前路径,在浏览器环境运行会触发文件下载。
日期 | 请求数 |
---|---|
2 日 | 1,162 |
3 日 | 631 |
4 日 | 1,250,557 |
5 日 | 3,923,019 |
6 日 | 2,416,396 |
7 日 | 4,957,792 |
2022 年 4 月 6 日 14 时,Twikoo 官方文档评论区数据库告警,连接数超限,业务未中断,未处理。
2022 年 4 月 6 日 21 时,虹墨空间站评论区云函数告警,业务未中断,未处理。
2022 年 4 月 7 日 7:40 ~ 10:40,虹墨空间站评论区云函数持续告警,已确认最新评论接口受到攻击。
2022 年 4 月 7 日上午,虹墨空间站下线最新评论接口,Twikoo 官方文档云函数切换到维护状态。
2022 年 4 月 7 日 15:00,Twikoo v1.5.2 版本发布,新增资源防刷功能尝试抵御此次攻击。
2022 年 4 月 7 日 15:33,Twikoo 官方文档评论区切换到备用环境。
2022 年 4 月 7 日 16 时,Twikoo 官方文档评论区备用环境受到相同来源攻击。
2022 年 4 月 7 日 18:35,虹墨空间站 CDN 受到攻击,在同一分钟内触发流量告警、流量封顶触发告警阈值、流量封顶阈值触发,CDN 自动关停,攻击共产生了 3 GB 流量。
2022 年 4 月 7 日 19 时,虹墨空间站切换 CDN,恢复正常访问。
2022 年 4 月 7 日 19:53,Twikoo 官方文档评论区切换回主环境,释放备用环境。
2022 年 4 月 8 日 8 时至 4 月 9 日 8 时,Twikoo 官方文档评论区云函数共处理 2,796,722 次请求,资源防刷功能缓解了攻击,数据库和云函数使用量再无明显上升,业务正常运行。
2022 年 4 月 9 日 10 时,虹墨空间站评论区云函数和数据库同时告警,最新评论接口再次受到攻击,人在外面,未及时处理。
2022 年 4 月 9 日 11 时,虹墨空间站评论区数据库资源超出配额,停服,评论区关闭。
2022 年 4 月 9 日 13 时,针对 Twikoo 官方文档评论区云函数的攻击停止,攻击共持续 3 天。
2022 年 4 月 9 日 14 时,虹墨空间站评论区临时切换为 utterances。
本次攻击目标为虹墨空间站 CDN、虹墨空间站评论区、Twikoo 官方文档评论区,已知同样受到攻击的还有 Waline 官方文档评论区和 hexo-theme-butterfly 主题评论区,无人承认发起了本次攻击,对本人造成的财产损失为 0,所有攻击波次都在短时间内得到处理。
处理攻击的原则:
https://ntp.msn.cn/edge/ntp
,就这么一个新标签页,不仅加载慢,还有一堆控制台报错。然而浏览器还没有提供修改新标签页地址的功能。虽然安装浏览器插件可以实现,但是浏览器插件修改新标签页时,会有弹窗提示插件修改了新标签页。本文提供一种通过注册表完美修改新标签页的方法,已在 Microsoft Edge 版本 99.0.1150.46 测试有效。Win 10 家庭版 / Win 11 家庭版无效。
edge-policies.reg
注册表文件,内容如下:1 | Windows Registry Editor Version 5.00 |
双击该注册表文件,导入注册表。
打开 Microsoft Edge,从地址栏输入 edge://policy/
打开,点击 “重新加载策略”,如果看到 NewTabPageLocation 的状态为 “确定”,你就成功了。
about:blank
about:blank
想知道原理?我们先看 Microsoft Edge - 策略 这篇文档的官方解释:
NewTabPageLocation
配置新选项卡页 URL
此策略确定创建新选项卡时(包括打开新窗口时)打开的页面。 如果启动页设置为打开新选项卡页,则该策略也会影响启动页。
此策略仅在加入 Microsoft Active Directory 域的 Windows 实例、已注册设备管理的 Windows 10 专业版或企业版实例,或者通过 MDM 托管或通过 MCX 加入域的 macOS 实例上可用。
我们未加域的个人电脑直接修改这个策略是不会生效的,以上注册表文件可以让浏览器 “以为” 系统通过 MDM 托管,从而使 NewTabPageLocation
策略生效。
正则表达式作用:
描述了一个规则,通过这个规则可以匹配一类字符串。
完成字符串的查找、验证和替换
1 | // 1.字面量创建 |
元字符 | 描述 |
---|---|
. | 查找除了换行和行结束符以外的所有字符。 |
\ | 将下一个字符标记为一个特殊字符、或一个原义字符、或一个引用 |
/ | 正则边界符 |
^n | 边界符,匹配任何开头为 n 的字符串或表示“非” |
n$ | 匹配任何结尾为 n 的字符串。 |
\w | 查找字母、数字、下划线 |
\W | 查找除了字母、数字、下划线的非单词字符。 |
\d | 查找数字。 |
\D | 查找非数字字符。 |
\s | 查找空白字符。 |
\S | 查找非空白字符。 |
\n | 查找换行符。 |
\r | 查找回车符。 |
量词 | 匹配数量 |
? | 表示量词或禁止贪婪 |
[] | 原子表 |
() | 原子组 |
断言匹配 | 相当于匹配条件 |
|- 量词仅作用于它前面紧跟的字符或组||
量词 | 描述 |
---|---|
n+ | 匹配任何包含至少一个 n 的字符串。 |
n* | 匹配任何包含零个或多个 n 的字符串。 |
n? | 匹配任何包含零个或一个 n 的字符串。 |
n{X} | 匹配包含 X 个 n 的序列的字符串。 |
n{X,Y} | 匹配包含 X 至 Y 个 n 的序列的字符串。 |
n{X,} | 匹配包含至少 X 个 n 的序列的字符串。 |
模式修正符意在改变运行方式
模式 | 描述 |
---|---|
i | 不区分大小写 |
g | 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止,只匹配一个叫做”不贪婪”)。 |
m | 执行多行匹配。使边界字符 ^ 和 $ 匹配每一行的开头和结尾 |
模式可组合使用,不区分顺序,如: /gi
表达式 | 描述 |
---|---|
[0-9] | 查找任何从 0 至 9 的数字 |
[a-z] | 查找任何从小写 a 到小写 z 的字符。 |
[A-Z] | 查找任何从大写 A 到大写 Z 的字符。 |
[adgk] | 查找给定集合内的任何字符。 |
[^adgk] | 查找给定集合外的任何字符。 |
正则表达式中以一对括号()包裹的运算内容称为原子组, 但也有()不是原子组的情况,需要区分
用处
1 | const str = ` |
如上述内容,要想匹配出完整的h标签,正则需使用原子组:
str.match( /<h[1-6]>.</h[1-6]>/g)
但会匹配出h标签前后不一致的数据
为使前后保持一致,可使用原子组:
str.match( /(<h[1-6])>.</\1>/g)
原子组的引用
1 | const reg1 = /<(h[1-6])>(.*)<\/\1>/ig; |
1 | str.replace(reg,(v,...args)=>{ |
3.原子组别名
当觉得$1 $2 不够清晰明了时,可以为原子组起别名
起名: (?<自定义名称>)
使用: $<自定义的名称>
1 | const reg2 = /<(h[1-6])>(?<two>.*)<\/\1>/ig; |
上面的量词中看到,” ? “表示0个或一个,表示可选;
除此之外,“ ?”还有禁止贪婪的作用;
如何区分?
1 | // 量词加?表示禁止贪婪,往最少的一个方向去 |
断言 | 描述 |
---|---|
?=n | 匹配任何其后紧接指定字符串 n 的字符串。 |
?!n | 匹配任何其后没有紧接指定字符串 n 的字符串。 |
?<=n | 匹配任何其前面紧接指定字符串 n 的字符串。 |
?<!n | 匹配任何其前面没有紧接指定字符串 n 的字符串。 |
举例:电话号码模糊匹配
1 |
|
量词 | 描述 |
---|---|
lastIndex | 一个整数,标示开始下一次匹配的字符位置。 |
1 | // 因为exec实际上是一个迭代器,正则有一个lastindex的属性, |
方法 | 描述 |
---|---|
exec | 匹配字符串,返回找到的值,并确定其位置。迭代器,lastindex |
test | 在所搜索的字符串中是否存在正则表达式模式对应的匹配。返回 true 或 false。 正则验证 |
方法 | 描述 |
---|---|
match | 找到一个或多个正则表达式的匹配。 |
replace | 替换与正则表达式匹配的子串。 |
split | 根据正则匹配到的内容分割字符串数组。 |
search | 搜索字符串中是否存在满足正则的字串,返回索引值 |
?journal=true&w=majority
;1 | mongoexport --uri 这里换成刚才复制的地址 --collection comment --type json --out twikoo-comments.json |
上周,jsDelivr 备案许可被注销,导致本站大量静态资源加载失败,遂寻找更稳定的 CDN 替换,但是,替换 CDN 治标不治本。几天后,我在 GitHub 看到了 freecdn 这个项目,很好地解决了这个问题。
freecdn 是一个纯前端的 CDN 解决方案,用于降低网站流量成本,同时提高网站稳定性、安全性,并且无需修改现有的业务逻辑。
互联网上有很多免费的公共库 CDN,例如
cdnjs
、jsdelivr
、unpkg
,但哪个最稳定,始终没有明确的答案。现在你无需纠结这个问题,随意选择即可。freecdn 可根据用户的网络状况,实时切换到合适的 CDN。
本文将会利用 freecdn 自动选择公共库的特性,加速 hexo icarus 站点。
themes/icarus/layout/common/head.jsx
文件,在 <head>
后增加一行 <script src="/freecdn-loader.min.js"></script>
hexo clean && hexo g
npm i -g freecdn
cd public && freecdn find --save && freecdn js --make
hexo d
或手动部署博客如果博客访问正常,你已经成功了一半!打开控制台网络标签,可以看到资源是从 Service Worker 加载的——
freecdn 大致做了以下事情:
freecdn-loader.min.js
freecdn-loader.min.js
,安装 Service Worker问题来了,由于本站的资源本来就从 CDN(jsd)加载,并不包含在 public 打包结果中,导致只有极少请求利用了 freecdn,大量请求依然走 jsd。若想解决这个问题,只好从 npm 仓库上挨个下载需要的资源,全部合并到自己的仓库管理,好在依赖的第三方资源不多,也就 8 个,半个小时足以搞定。
1 | ├─clipboard |
如果 freecdn 能够扫描 public 中的 CDN 网址,并生成清单文件的话,就不需要这么麻烦了,然而技术实现应该很难吧。
1 |
|
这个 bug 从 Windows 7 延续到 Windows 10,包括 Windows Server,依然没有解决,Windows 11 的任务栏大改,似乎解决了,但 Windows 11 的资源管理器卡顿问题更让人苦恼……
解决方法是安装 7+ Taskbar Tweaker(官网、源码 和 下载地址),软件里的功能可以不开,设为开机自启并保持软件在后台运行即可。
这时候马上有小伙伴会问,还要安装软件?不安装不行吗?这是 Windows 的 bug,安装软件是影响最小的了。但这个软件只占用极低的磁盘空间(803 KB)和极低的内存(0.1 MB),并且可以隐藏托盘图标(点击设置,勾选隐藏任务栏图标),对于强迫症而言还是可以忍受的。
]]>1 | webpackChain |
然而替换的过程没有那么顺利,编译打包虽然没有任何报错,但运行时字体文件报了 404。
检查打包结果发现,打包后的 CSS 包含的字体路径是错误的:
1 | dist |
1 | @font-face { |
由于 CSS 文件中写的是字体的相对路径,浏览器会请求 css/fonts/abc.ttf
,报了 404 找不到。
搜索了一下午,找到了以下相关问题:
都没有得到解决,其中一个答案是把 asset/resource
换成 asset/inline
,虽然可以解决,但如果字体过大,inline 会大幅增加 CSS 文件大小,所以不适用。
最后,在 mini-css-extract-plugin 的 issue 中找到了解决方法。
原因是我配置的 webpack output.publicPath
是 “./
“,改为 “auto
“ 即可被正确识别,打包后的 CSS 会以 “../fonts/abc.ttf
“ 的路径引用字体。
近年来,Serverless 成为云计算领域热门词汇。早在 2014 年,亚马逊就在 AWSre:Invent 2014 大会上推出了 AWSLambda,赢得了开发者的广泛好评。2018 年,国内云服务厂商相继开始跟进,阿里云、腾讯云也推出了自己的 Serverless 云服务。今天我们就通过国内云厂商的案例来了解,Serverless 是什么?为什么需要 Serverless?它是如何降低软件开发成本,同时增加软件开发效率的?
Serverless[1]的概念简单易懂,Serverless 顾名思义即 “无服务器”。开发者只需要把源代码发布到 Serverless 平台,而无需关心如何部署与维护,也不需要关心 Serverless 如何启动、如何接受请求、有多少个执行机、如何自动扩缩容。为了实现 Serverless 这一目的,云平台通常会提供 FaaS 和 BaaS 两种服务的支持——
我们可以把 Serverless 理解为运行在 FaaS 中的,使用了 BaaS 的函数[2]。
相比于传统服务依赖于基础设施(如云服务器)搭建,Serverless 开发者不需要关心基础设施建设,而基础设施提供的集群监控、服务治理、配置管理、日志等能力,已经包含在了 Serverless 提供的服务当中。
前后端分离是目前主流的开发模式,后端开发 RESTfulAPI 供前端调用,需要专业的后端开发人员,搭建复杂的开发环境,例如 SpringBoot、MySQL、Redis、RabbitMQ、Docker 等。后端开发完成之后,前后端需要进行联调工作。开发成本和运维成本较高。绝大多数业务场景其实并不复杂。例如,我们需要一个 HTML 转 PDF 服务,在传统的后端开发环境下,搭建环境、针对稳定性、高并发进行优化等工作,要花费数倍于业务开发的时间,费时费力。我们需要一套解决方案,降低非业务需求的开发难度,把精力投入到业务开发中。
Serverless 可以从 3 个方面节约项目成本。
以阿里云函数计算为例,几乎兼容所有的主流编程语言。
函数是无状态的,也就是说,多个运行中的函数实例不会共享内存,不会相互干扰。
说了这么多 Serverless 的好处,具体在哪些业务场景可以用 Serverless 开发呢?
在小规模项目中,后端只有一些简单的接口,例如 CRUD,此时熟悉 Node.js 的前端开发人员利用 Serverless 即可完成接口的开发,无需后端开发人员介入,降低了项目的成本。
以一个仓库库存管理小程序为例,开发者只需在浏览器中写几行代码,即可搞定数据库查询接口。
对 SEO 要求较高的 SPA 项目,往往会选择使用服务端渲染的方式应对搜索引擎爬虫程序,爬虫程序访问间隔长,服务端渲染消耗的服务器资源少,为此专门购买服务器就显得没有必要了,编写 Serverless 应对爬虫请求,可以节省服务器资源成本。
传统动态 CMS(如 WordPress)成本高、访问速度慢、资源消耗大,传统静态生成器 CMS(如 Hexo)维护门槛高,不支持动态内容。为了解决二者的缺点,Jamstack 出现了。使用网站生成器(例如 Hexo)预渲染整个网站,使用 Headless CMS(无头 CMS)管理动态内容,使用 HTTPAPI 增强网站的功能[3]。这种技术的出现很大程度上依托于各大云厂商提供的 Serverless Function 能力。我们可以在 Serverless 上部署无头 CMS(例如 Ghost),以及评论系统等插件,动态扩展网站功能,构建集快速、稳定、低成本、易于维护为一体的网站。
Serverless 不仅支持通过 HTTP 调用,还支持定时触发、消息队列等触发方式。因此,智能家居控制、定时任务、持续集成、持续部署、消息队列的消费者等场景,都可以使用 Serverless 实现。互联网自动化(IFTTT)是“If This Then That”的缩写,是一个典型的事件驱动型工具,帮助人们利用各网站的开放 API,实现跨服务联动、硬件联动等好玩的玩法,唯一的门槛在于,你需要一台服务器来处理各种事件,Serverless 能够完美地胜任这个角色。
Serverless 可以构建应用程序的图像和视频处理服务。可以使用 Serverless 服务来执行诸如动态调整图像大小或更改不同目标设备的视频转码之类的操作。
使用 Serverless 前,要清楚了解 Serverless 的收费模式,无论是测试,还是生产,都需要特别留意资源用量,针对业务,设置合适的监控告警和资源用量上限。Serverless 费用通常由以下几部分构成:
在开发过程中,我们会发现,云函数首次调用很慢。这就要从云函数的执行机制说起了。云函数存在两种启动:
云函数如果在一定时间内(几十分钟)没有被调用,那么平台会收回分配的计算资源,直到函数被调用前,再分配计算资源,这种情况下,会发生冷启动。
冷启动在某些场合会影响用户体验,比如,在一个评论系统中,读取评论接口的调用频率会远高于提交评论接口的调用频率,以单独的云函数实现提交评论接口,会导致提交评论接口屡次冷启动,用户提交评论缓慢。这种场景下我们可以使用“单一云函数”原则,由同一个云函数实现读取和提交,使用路由分发请求,消除不同业务逻辑间的重复冷启动时间[4]。
1 | // 云函数入口点 |
除了以上方法,我们还可以为必要的函数插入一段心跳(heart beating)逻辑,使用特定的参数触发,不进行任何操作,直接返回,然后为该函数添加定时触发器,每隔一段时间调用心跳逻辑,通过牺牲少量函数资源,阻止函数的运行资源被回收。
如果云函数拥有较多的依赖库或公共代码文件,会给在线编辑和部署带来不便。因此,为了管理这些依赖,诞生了函数层这一概念。和 Docker layer 相似,使用层管理,可以将依赖放在层中而不是部署包中,可确保部署包保持较小的体积。加快部署,方便在线编辑。
除了公有云服务提供商提供的 Serverless 云服务外,我们还可以在私有云中部署 Serverless,这在项目不方便部署到公有云时非常有用。Nuclio 即是这样的平台,只需一行命令,即可启动 Nuclio。
1 | docker run -p 8070:8070 -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp nuclio/dashboard:stable-amd64 |
Serverless 不能完全取代传统后端服务,在业务选择使用 Serverless 开发之前,我们还需要了解 Serverless 有哪些“坑”。
Serverless 架构的诞生,降低了软件开发成本,提升了软件开发效率。使用 Serverless,我们不再需要过多关注服务端的运维等不熟悉的领域,只需要专注于业务的开发、专注于产品的实现。我们需要关心的事情变少了,但我们能做的事情更多了。如果要用一句话来总结 Serverless,那就是 Less is More。
[1] CNCF Serverless Whitepaper v1.0 - https://github.com/cncf/wg-serverless/tree/master/whitepapers/serverless-overview
[2] Serverless 掀起新的前端技术变革 - https://zhuanlan.zhihu.com/p/65914436
[3] Jamstack,下一代Web建站技术栈? - https://zhuanlan.zhihu.com/p/281085404
[4] 腾讯云云开发云函数 之 代码共用 - https://www.imaegoo.com/2020/tcb-functions-dry/
[5] We Burnt $72K testing Firebase + Cloud Run and almost went Bankrupt - https://blog.tomilkieway.com/72k-1/
]]>本文首发于 原银科技公众号 和 中原银行 InfoQ,转载请注明出处。
暂时还没有适配手机浏览器,有时间会适配一下。 已经适配手机浏览器啦!
博主已经考过啦!考场计算器与本页面的计算器是一模一样的!提示:点击输入框中右侧的按钮可以打开加减乘除计算器。
最后祝大家考试顺利!
]]>
开源:OBS(直播推流软件,录屏功能也非常强大)
收费:Bandicam(收费录屏软件中自认为最好用的)
开源:ScreenToGif
免费:XnViewMP(图片批处理功能非常好用,商用收费)
开源:GIMP(GNU 出品)
收费:Adobe Photoshop(Ps)
免费:Avidemux(用于简单的剪辑、合并,处理速度极快)
开源:Shotcut(同事推荐)
免费:DaVinci Resolve(有收费版,免费版足矣)
收费:Adobe Premiere(Pr)
免费:Cool Edit(CE,老剪辑软件了)
收费:Adobe Audition(Au)
开源:FFmpeg(命令行转码工具,有学习成本,无中文)
免费:XMedia Recode(功能强大,可调节的参数非常多)
收费:Xilisoft Video Converter Ultimate(功能强大,上手简单,转码快,可惜收费)
原文链接:https://www.tomshardware.com/how-to/restore-windows-10-explorer-windows-11,翻译:iMaeGoo
打开注册表编辑器。你可以在 Windows 11 中通过按 Win + R 并在运行框中输入 regedit
来执行此操作,或者你可以使用搜索功能搜索 regedit
。如果用户帐户控制要求许可,请单击是。
导航到 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions
如果不存在,则在左侧创建一个名为 Blocked
的注册表项,并导航到它。
在右窗格中右键单击并选择 新建
-> 字符串值
。出现一个新条目,名称为“新值 #”和一个数字。
将你的值重命名为 {e2bf9676-5f8f-435c-97eb-11607a5bedf7}
现在你的计算机现在应该显示经典的 Windows 10 文件资源管理器,如果你想返回 Windows 11 的文件资源管理器,只需删除刚刚创建的字符串值,再重新启动计算机。
]]>首先需要你拥有修改博客主题的能力。
twikoo.init()
之前),引入相关的 JS 和 CSS 文件1 | <!-- lightGallery --> |
twikoo.init
代码所在位置,进行修改1 | twikoo.init({ |
之所以写这个是因为网上的同类工具要么离不开后端操作,要么广告一堆,用着不顺手。
简单一点。
1 | // <script src="https://cdn.jsdelivr.net/npm/base64-js@1.5.1/base64js.min.js"></script> |
1 | gsettings set org.gnome.desktop.interface enable-animations false |
想要重新开启动画,只需要执行
1 | gsettings set org.gnome.desktop.interface enable-animations true |
看看百度的答案都是些啥,还需要安装 compizconfig-settings-manager,其实一行命令就解决啦。
]]>首先要确定自己所用的博客主题支持 Twikoo path 配置,否则需要自己修改主题源码添加 path 配置。
设置主题的 Twikoo path 配置为 window.TWIKOO_MAGIC_PATH||window.location.pathname
然后在所有需要共用评论区的页面正文中增加以下代码 <script>window.TWIKOO_MAGIC_PATH="评论区名称"</script>
把中间的“评论区名称”替换为你指定的名称,共用的页面请起 相同的 评论区名称,其他页面不做改动即可。
试试看!
]]>转自:https://blog.csdn.net/weixin_32496175/article/details/114013102
1 | ((function () { |
弊端:访客点击继续按钮前,依旧可以审查元素,并不能有效阻止。
破解方式:
打开新标签页,打开 F12 控制台 Sources 选项卡,点亮右侧的 Activate breakpoints,再从地址栏进入目标网站即可。
转自:https://blog.csdn.net/qq_21567385/article/details/108473235
利用了控制台会读取 image element 的 id 的特性。
1 | (function() { |
破解方式:
使用油猴脚本清空控制台。
1 | // ==UserScript== |
这是非常激进的做法,基本能够应对各种反审查策略,但在 AJAX 盛行的现在,多少网页离了 JS 还可以正常展示呢?
PC 版米游社( http://bbs.mihoyo.com/ )的反审查做得也非常到位,有时间会研究如何破解。(学习目的!)
]]>如果你还没有 Cloudflare 账号,可以申请一个。
登录 Cloudflare 后,进入 Workers 页面,点击 KV。
添加一个 Cloudflare KV,起名 ref,用于记录访问记录。
创建 Cloudflare Worker,起名 img,用于记录请求信息,并转发图片资源请求。
代码如下:
1 | addEventListener('fetch', (event) => { |
将 KV ref 的命名空间绑定到 Worker img。
在仓库的 README.md
中插入图片
1 | ![](https://img.imaegoo.workers.dev/image.png) |
到 KV ref 中查看效果
利用同样的思路和方法,我们还可以追查网站文章未经授权的转载,试试看!
]]>1 | Promise.resolve(1) |
1 | 1 |
1 | const promise = new Promise((resolve, reject) => { |
1 | 1 |
1 | const promise1 = new Promise((resolve, reject) => { |
1 | promise1 Promise { <state>: "pending" } |
1 | setTimeout(() => console.log(5), 0) |
1 | 1 |
1 | const promise = new Promise((resolve, reject) => { |
1 | then: success1 |
1 | const promise = new Promise((resolve, reject) => { |
1 | once |
1 | Promise.resolve() |
1 | then: Error: error!!! |
1 | const promise = Promise.resolve() |
1 | SpiderMonkey: |
1 | Promise.resolve(1) |
1 | 1 |
1 | Promise.resolve() |
1 | fail2: Error: error |
1 | Promise.resolve() |
1 | fail2: Error: error |
1 | process.nextTick(() => { |
1 | end |
1 | const first = () => (new Promise((resolve, reject) => { |
1 | 3 |
1 | var p = new Promise((resolve, reject) => { |
1 | The Fails! |
1 | var p = new Promise((resolve, reject) => { |
1 | Uncaught (in promise) Error: The Fails! |
1 | var p = new Promise((resolve, reject) => { |
1 | Error: The Fails! |
1 | new Promise((resolve, reject) => { |
1 | [No output] |
1 | Promise.resolve('Success!') |
1 | SUCCESS! |
1 | Promise.resolve('Success!') |
1 | The fails! |
1 | const first = () => (new Promise((resolve, reject) => { |
1 | 3 |
1 | async function async1() { |
1 | 1 |
参考资料:
https://zhuanlan.zhihu.com/p/34421918
https://zhuanlan.zhihu.com/p/30797777
https://zhuanlan.zhihu.com/p/98164787
https://juejin.cn/post/6844903986210816013#heading-3
https://juejin.cn/post/6844903605250572302
于是 Vite 诞生了,一起诞生的还有 VitePress。好耶!虽然 VitePress 仍处于 WIP 阶段,告诉我们不要在任何地方使用,但我们可以提前对比一下,它究竟能比 VuePress 快多少?我们使用基于 VuePress 的 Twikoo 文档测试一下。
1 | yarn add -D vitepress |
VitePress 中 themeConfig.sidebar
的配置,较 VuePress 有些不同,需要新建 .vitepress
目录,对原先的配置做一点点改动
1 | module.exports = { |
1 | module.exports = { |
VitePress 没有把 README.md 渲染成首页,需要把 README.md 重命名为 index.md。
多次测试在机械硬盘上两者的编译速度,VuePress 的编译时间在 30 ~ 50 秒之间,而 VitePress 的编译时间基本都在 6 ~ 7 秒,遥遥领先。
1 | $ vuepress build docs |
1 | $ vitepress build docs |
基本一致,可以看出 VitePress 存在一些渲染上的小区别。
]]>main
函数 return 时,执行进程会被立即冻结。这一点在官方文档Node.js 8 的异步行为中有提到。对于异步函数,主流程执行完成后,函数实例进程会被冻结,进程中的所有异步任务会暂停执行,直到这个进程被再次唤起。
另一方面,如果函数实例进程由于某些原因没被复用(例如更新了函数代码),这个异步流程中的代码就永远不会被执行。
但是有些场景下,云函数需要很长的执行时间,例如,Twikoo 通过 Akismet 检测垃圾评论的过程。按照特性,在检测过程结束前,就不能异步检测,提前返回结果给前端,否则检测进程就会被冻结,导致检测失败。我们只能 await 同步检测,造成请求响应慢,用户体验差。
按照 Java 的习惯,我们会启动新的线程执行长时间的任务,在云函数中怎样实现?
首先 node.js 想要实现多线程是不可能的,那我们换个思路,可以实现多进程吗?可以通过 “云函数调用云函数” 实现多个云函数进程并发执行吗?可以。
1 | try { |
callFunction 提供了请求超时时间的设置,即使请求超时,被调用的云函数也是会继续执行完的。那我们就利用这一点,设置较短的 timeout 来实现异步。这样,用户调起的云函数就能够迅速返回结果,垃圾评论检测就可以在另一个进程中慢慢执行了。
肯定有人会问,想要保护起来这种“异步云函数”,只能内部调用,不能外部调用,该怎么实现?这里也提供一个简单的方法。
1 | exports.main = async (event, context) => { |
相关完整代码请查看 Twikoo 源码
]]>Twikoo 评论系统要实现导入功能,导入,就需要上传文件。
通过调用云函数,我们能够传递 string、number 等简单的参数,想要上传文件?不太行。
想到云开发环境有一块默认开通的 COS 空间,这块空间允许登录用户上传文件,只要利用这片空间,就可以实现将文件上传给云函数的功能了。
首先需要用户选择文件,先写一个选择文件的 input 和一个上传文件的 button。
1 | <input type="file" value="" ref="inputFile" /> |
再编写上传的方法。
1 | // 获取用户选择的文件 |
这样一个上传功能就完成了。但我们还需要服务器获取到上传的文件,怎样获得呢?
1 | // 通过接收到的 fileID 读取云存储中的文件 |
好了,云函数已经成功取得前端上传的文件内容了,接下来就可以实现导入逻辑了。
本文仅摘部分关键代码解读,完整代码可在 Twikoo 中参考
最终实现了下图所示的导入功能(故意上传了一个错误的文件)
]]>当小程序中使用第三方字体时,在 iPhone 11 和 iPhone 12 机型下
这个问题只能在几个特定的机型下出现,不用第三方字体也没有这个问题,安卓机型和开发者工具也重现不了,甚至 iPhone 12 mini 用同一版本也不能重现。
微信版本:7.0.18
小程序基础库:2.14.0
iOS:14.2
这未免也太奇怪了。
代码片段地址:https://developers.weixin.qq.com/s/wgOVEgmQ7Cmz
1 | <view class="page" wx-if="{{ ready }}"> |
1 | Page({ |
1 | .page { |
使用微信开发者工具真机调试功能,发现 text 的宽度只有正常的一半宽度,尝试设置 text 的宽度,因为 text 属于 inline 元素,所以没有效果……
于是乎,想到既然中文字正常,那我们只要在英文字中加入中文字符,是不是能解决问题呢?
如果想让文字居中,就在文字左右各加一个全角空格“ ”
如果想让文字右对齐,就在文字右边加一个全角空格“ ”
其实就是,只要让文本不全是英文和数字,就不会出现问题。
(⊙﹏⊙)……说是解决办法,其实是一个 workaround,等着官方修复吧……
社区相应的 bug:https://developers.weixin.qq.com/community/develop/doc/0006cc3bd7056063605b97a2353c00
]]>不同的云函数可以共用代码文件(目录)吗
未上线
如果是简单的云函数,这一点还能接受,在开发 Twikoo 评论系统的过程中,云函数要实现的 API 越来越多,逐渐让我发现了它的弊端:
显然违反了开发的 DRY 原则,这迫使我开始思考解决方案。
正常的思维是,一个 API 写一个云函数,如果将云函数合并,用一个云函数实现不同的功能,能否解决这样的问题呢?
可以!
经过改造后的云函数,只保留了一个云函数入口点,通过传入 event,来调用不同的分功能,不同的功能也终于可以复用代码了。
1 | // 云函数入口点 / entry point |
工作上正在开发的一款小程序,需要链接到京东购物的一个活动页面。经过搜索发现,除了在小程序内嵌 Webview,小程序内不能直接跳转一个网页,但是京东也是有自己的小程序的,我们可以跳转到京东的小程序吗?查找文档发现可以用 wx.navigateToMiniProgram 打开另一个小程序。
1 | wx.navigateToMiniProgram({ |
现在需要的就是京东小程序的 appId 和活动页面的 path 了!
一番操作后,我发现微信 APP 上既不能获取到小程序的 appId 也不能获取到活动页面的 path,若要获得这两样东西,得开启调试才行,想开启调试,至少要成为小程序开发者……
京东小程序的开发者,我怎么可能拿得到嘛,我连他们的开发者都接触不到!
小程序页面至少是可分享的,如果是配置成完全不可分享的小程序,此方法不可用。
拿“抽奖助手”小程序做例子吧。
https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync
的请求;AddMsgList[0].Content
,看到一个转义的 XML 字符串;<weappinfo>
,找到类似下面的这一段数据;1 | <weappinfo> |
wx01bb1ef166cd3f4e
”即为我们要找的 appIdpages/lucky/lottery/detail.html?id=80018XBB8Mn&home=1
”删除里面的 .html
后,即为我们要找的 path添加 2 个文件
1 | module.exports = { |
1 | <template> |
vuepress v1.5.4
]]>
难道就没有一个完美的方案?
在咕咕咕了近三个月后,我自己搞出了一套评论系统,并命名为 Twikoo。
欢迎访问 twikoo.js.org 了解更多。
滚回去修 bug 了
AyagawaSeirin 提出了一个 Valine 隐私安全漏洞,发送请求中响应内容明文暴露评论者IP、邮箱等隐私内容,所以我就去查了一下 LeanCloud 文档,发现可以手动更改字段权限,但是,如果设置 mail
客户端不可见,将不会显示评论者的 Gravatar,转为显示默认头像,因为原版是取到明文邮箱后再转 MD5 取头像的。想到的解决办法是新增一个可见字段存储 mail 的 MD5,需要改 Valine 源码,还需要处理现有数据。
以下是我实现的魔改版本,基于 Valine.min.js 版本 1.4.14 修改。该魔改版新增一个可见字段(mailMd5
)存储 mail 的 MD5,并提供了脚本处理现有评论数据。
访问 LeanCloud 控制台 > 存储 > 结构化数据
选择 Comment Class,分别点击 mail 和 ip 相应字段的下拉菜单,选择编辑
勾选”客户端不可见”后,客户端发起查询的时候,返回的结果将不包含这个字段
* 即使用 AppKey 指定字段名查询,也不会返回字段值,足够安全。
请同样确认 class 的权限配置
克隆本仓库
1 | # 克隆 |
打开 migrate.js
,修改里面的 appId,appKey,masterKey,serverURL 为自己的
执行脚本
1 | node migrate.js |
替换博客的 Valine.min.js
为本仓库到 valine.js
,可以使用 CDN 地址:
https://cdn.jsdelivr.net/npm/@imaegoo/valine@1.4.1-4.1/valine.min.js
测试一下,头像是否正常加载,API 是否没有返回 mail 和 ip
如果你对魔改版感到不放心,可以检查检查我都改了些啥
]]>直到我在无意间查看 Reabble 阅读器的 CSS 样式时,发现了 @media (prefers-color-scheme: dark)
选择器。
来自:prefers-color-scheme - CSS(层叠样式表) | MDN
prefers-color-scheme CSS 媒体特性用于检测用户是否有将系统的主题色设置为亮色或者暗色。
简而言之,就是可以实现随系统(或浏览器)的深、浅色模式设置,改变网页配色。
我觉得这是比按时间切换更好的一个实现,跟随系统设置比跟随时间更加人性化一些,毕竟还有我这种,白天开深色,晚上开浅色的异类(逃)
]]>事情的起因是,我需要一个存放未分类整理知识点,以及收藏转载文章的私人知识库,和 iMaeGoo’s Blog 区别开来。
我尝试过简书、语雀、Evernote、OneNote、有道云笔记,对它们的 markdown 支持、导出能力、搜索能力、容量、安全性都有体会。
最后我决定建一个私人 Git 仓库,用 markdown 来记笔记。然后通过 CI/CD 自动构建到一个叫 iMaeGoo’s Diary 的 VuePress 网站。写笔记 Notepad + Git 就能搞定,还能自由选择多种多样的 markdown 编辑器,手机端也可以通过在线 IDE 更新内容,VuePress 的搜索非常好用,安全性也完全在自己的掌控范围之内。
反正是知识库嘛,我配置了完全公开,方便自己随时随地查看,但由于是未经整理的知识库,也不建议访客去看啦。
问题就来了,有些笔记包含了敏感信息,怎么在公开的知识库中保护这类信息?
在寻找 VuePress 加密时,我发现了 vuepress-plugin-encrypt 这个好用的插件,使用了 aes-128-ctr
来加密内容,你可以直接查看它的英文官方文档。
1 | yarn add -D @oak-tree-house/vuepress-plugin-encrypt |
1 | module.exports = { |
package.json
增加加解密的命令1 | { |
encrypt
和 decrypt
需要放在最前,否则会遇到错误 error: unknown option '--source-dir'
.gitignore
列表1 | /keys.json |
/keys.json
keys.json
1 | { |
1 | ## test |
yarn encrypt
,你将会发现上一步的内容被自动替换成密文1 | ## test |
最新的完整配置参见官方文档
1 | module.exports = { |
主要是 Bing 找了许多 libraries。效果在 Chrome for Windows 上都不理想,要么滚动很生硬,要么就是太复杂,就自己实现了。
本来是 PC only 的,写好后测试了一下移动端,是兼容的,效果也还不错……
不过反正移动端都自带惯性滑动了
配色参考:https://color.adobe.com/zh/%E6%B5%81%E8%A1%8C%E8%89%B2-color-theme-4031536/
1 | <div class="columns" style="width: 100%;"> |
1 | .ss-container { |
1 | document.getElementById('smooth-scrollable').onscroll = (e) => { |
transform: translateY();
控制其上下移动transition: transform 1s;
,可以同时设置动画函数和持续时间根据这个思路,可以封装一个 JS 库,但是我好懒……
]]>1 | SCRIPT5022: Exception thrown and not caught |
未捕获的异常?EXM?你倒是说是什么异常啊?行号还是错的?点过去无法定位错误位置?hash-navigation.js
?我的项目里根本都没有这个 js 啊喂!
后来怎么解决的呢?因为这个错误是在滚轮滚动的时候打出来的,我在项目中各个 onScroll
方法外层加了 try catch 块。
1 | try { |
于是真相水落石出了。
某处代码迭代了 DOM 元素,而在 Edge 中,document.getElementsByClassName
的返回不支持迭代,其他浏览器不存在这个问题。
1 | const doms = document.getElementsByClassName('some-class') |
换一种兼容性更好的迭代方式就好了
1 | const doms = document.getElementsByClassName('some-class') |
如果你也遇到了这个异常,可以试试加 try catch 的办法,从而定位问题根源。
]]>1 | <div class="frame"> |
设置动画,分别控制小球 x 轴,y 轴,以及缩放比。先画张图,把小球 x 轴、y 轴的位置、缩放比与时间的关系用坐标系表示出来——
通过这张画图可以看出——
我们动画一个周期是 6 秒,理解了这些,就可以写出相应的 animation 出来了。
完整错误信息:
1 | 03-Jun-2020 07:52:22.772 SEVERE [main] org.apache.tomcat.jdbc.pool.ConnectionPool.init Unable to create initial connections of pool. |
提取关键信息:
1 | Caused by: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake |
得知 SSL 握手失败,于是我找了 Azure 的示例代码(https://docs.azure.cn/zh-cn/mysql/connect-java)来测,也是同样的问题。
又参考了《How to configure spring boot application to use SSL/TLS over MySQL?》去信任 Azure 的 CA 证书,仍然不起作用。
最后发现是我用的 mysql-connector-java 版本过低导致,我们使用的 Camunda 的 docker 镜像内置了 5.1.21
的数据库驱动,我的测试代码也是同样的版本,连接不上,只要升级到目前的最新版 5.1.49
,问题就解决了。
另一个坑,如果收到提示
1 | ERROR 9002 (28000): The connection string may not be right. Please visit portal for references. |
一般是连接用户名没有加实例名,比如数据库地址是 abc123.mysql.database.chinacloudapi.cn
,那么连接用户名要以 @abc123
结尾。
还有 Azure 整理了一个使用数据库时的常见问题列表,里面有很多问题都会踩到,建议看看——
https://docs.azure.cn/zh-cn/mysql-database-on-azure/mysql-database-tech-faq
]]>阅读下面的解决方法前,建议先阅读网页字体优化,了解一些基本知识,以及,为什么。
GBK 结尾的字体偏大的原因是包含庞大的繁体字库,大多数网页并不需要,可以使用 fontTools 得到字体的简体中文子集。
安装 Python 3.7 和 pip,再运行 pip install fonttools
来安装 fontTools。
运行 pyftsubset --help
查看命令帮助,得知需要 Unicode 列表来提取字体子集。
我们看一下 Unicode 表:
字符集 | 字数 | Unicode 编码 |
---|---|---|
基本汉字 | 20902字 | 4E00-9FA5 |
基本汉字补充 | 74字 | 9FA6-9FEF |
扩展A | 6582字 | 3400-4DB5 |
扩展B | 42711字 | 20000-2A6D6 |
扩展C | 4149字 | 2A700-2B734 |
扩展D | 222字 | 2B740-2B81D |
扩展E | 5762字 | 2B820-2CEA1 |
扩展F | 7473字 | 2CEB0-2EBE0 |
扩展G | 4939字 | 30000-3134A |
康熙部首 | 214字 | 2F00-2FD5 |
部首扩展 | 115字 | 2E80-2EF3 |
兼容汉字 | 477字 | F900-FAD9 |
兼容扩展 | 542字 | 2F800-2FA1D |
PUA(GBK)部件 | 81字 | E815-E86F |
部件扩展 | 452字 | E400-E5E8 |
PUA增补 | 207字 | E600-E6CF |
汉字笔画 | 36字 | 31C0-31E3 |
汉字结构 | 12字 | 2FF0-2FFB |
汉语注音 | 43字 | 3105-312F |
注音扩展 | 22字 | 31A0-31BA |
〇 | 1字 | 3007 |
* 转载自汉字 Unicode 编码范围
这里会遇到一个问题,基本汉字(4E00-9FA5)区间内,简体字、繁体字是交叉的,没有一个固定的简体区间和繁体区间,所以需要一个简体字的 Unicode 表,经过整理,我得到最终的 unicodes 文件,再加入 latin 的区间(0000-00FF),以及中文标点符号,作为参数传入 fontTools 获得字体子集。
你可以直接从 Gist 下载我整理好的文件:sc_unicode.txt,并和需要处理的字体放在一起。
1 | pyftsubset fang-zheng-hei-ti-gbk.ttf --unicodes-file=sc_unicode.txt |
该命令会压缩方正黑体,执行后可在同目录下找到 fang-zheng-hei-ti-gbk.subset.ttf
,字体大小变为原来的 27.6%
1 | 2020/05/13 10:53 2,823,032 fang-zheng-hei-ti-gbk.subset.ttf |
编译安装 Google woff2(笔者的环境是 Ubuntu 16.04)
1 | sudo apt-get install -y git g++ make |
再压缩字体
1 | ./woff2_compress ./fang-zheng-hei-ti-gbk.ttf |
1 | 2020/05/12 11:09 10,210,812 fang-zheng-hei-ti-gbk.ttf |
可见对方正黑体进行压缩后,压缩比 36.3%
如果配合去繁体使用,最终字体大小只有 1.09 MB (1,148,408 bytes),效果显著。
最终使用时,还需要考虑 woff2 的浏览器兼容问题,提供多种格式(woff 和 ttf)保证兼容。
themes/icarus/source/js
,并重命名为 pinyin.js
themes/icarus/layout/search
,并重命名为 insight.jsx
themes/icarus/source/js
,并重命名为 insight.js
themes/icarus/layout/search/insight.jsx
,加入拼音检索开关和依赖的 pinyin.js1 | diff --git a/src/view/search/insight.jsx b/src/view/search/insight.jsx |
insight.jsx
如下:1 | /** |
themes/icarus/source/js/insight.js
,在原有匹配代码基础上增加拼音匹配代码1 | diff --git a/asset/js/insight.js b/asset/js/insight.js |
insight.js
如下:1 | /** |
themes/icarus/include/style/search.styl
,调整拼音检索复选框大小和位置1 | diff --git a/include/style/search.styl b/include/style/search.styl |
search.styl
如下:1 | /* --------------------------------- |
我一直在用 Google Play 版本的 QQ,简洁没有花里胡哨的功能,要问我为什么不用 TIM?因为 TIM 实在太简洁了,连表情都不能下载。
今天突然发现 Play 里的 QQ 更新了!终于不是那个远古版本的 7.7.6 了。
我比较喜欢消息气泡,有时候我甚至可以看气泡认人,但我非常讨厌个性字体,一些字体的辨识度实在低,虽然可以双击查看消息,但能够屏蔽就舒服了。在 7.7.6 中我通过删除 Tencent/MobileQQ/.font_info
目录并创建同名文件来屏蔽字体,新版不起作用了。
找了一圈,发现是这个目录位置变了,现在是 Android/data/com.tencent.mobileqq/Tencent/MobileQQ/.font_info/
。
马上删掉,创建同名文件!
然后就遇到问题,QQ 学聪明了,删除了我创建的文件,然后重新加载了字体。
我又想到了给 000 权限,但是 Android 内部存储中的文件是不能设权限的,此路不通。
经过一番尝试,我找到了新的办法屏蔽字体,简而言之,就是用空文件替换所有的 ttf。
你可以用文件管理器来替换字体,但是字体太多,用 RE 一个个替换太麻烦,这里我们用 Termux 命令批量替换。
1 | apt update && apt upgrade |
1 | truncate --size 0 ~/storage/shared/Android/data/com.tencent.mobileqq/Tencent/MobileQQ/.font_info/**/*.ttf |
这个方法不能一劳永逸,好像没有一劳永逸的办法?如果你有什么更好的办法,欢迎评论!
首先结束运行 QQ,打开 RE 或类似的文件管理器,定位到如下路径:
1 | 根目录/data/media/0/Android/data/com.tencent.mobileqq/Tencent/MobileQQ/ |
修改 .font_info
目录权限为 000,再清空 .font_info
目录,搞定。
1 | <div class="buttons"> |
光有按钮肯定是不行的,一般我们还需要给按钮增加事件,比如点击下面的按钮,可以显示一条一言(Hitokoto)。
↑↑↑ 试着点击“显示一言”!
1 | <button class="button is-info" onclick="showHitokoto(event)">显示一言</button> |
1 | <progress class="progress is-info" value="20" max="100"></progress> |
Pixabay 是全球知名的图库网站及充满活力的创意社区,拥有上百万张免费正版高清照片素材,涵盖风景、人物、动态、静物等多种分类,你可以在任何地方使用 Pixabay 图库中的素材…
网易云音乐 是一款专注于发现与分享的音乐产品,依托专业音乐人、DJ、好友推荐及社交功能,为用户打造全新的音乐生活。
哔哩哔哩 是国内知名的视频弹幕网站,这里有最及时的动漫新番,最棒的ACG氛围,最有创意的Up主。大家可以在这里找到许多欢乐。
石墨文档 是全新一代云 Office 办公软件,支持多人在线协作编辑文档和表格,独有内容级安全,全过程留痕可追溯。PC 端和移动端全覆盖,随时随地远程办公。即写即存…
1 | <div class="tabs is-toggle"><ul> |
Icarus 主题以白色的简洁为主,但有时候我们希望在文章中用特别的样式注明一些内容,markdown 语法就不够用了,所以在此分享一下我的高级玩法。
1 | {% raw %}<div class="notification is-info">{% endraw %} |
Icarus 主题以白色的简洁为主,但有时候我们希望在文章中用特别的样式注明一些内容,markdown 语法就不够用了,所以在此分享一下我的高级玩法。
1 | {% raw %}<div class="notification is-success">{% endraw %} |
Icarus 主题以白色的简洁为主,但有时候我们希望在文章中用特别的样式注明一些内容,markdown 语法就不够用了,所以在此分享一下我的高级玩法。
1 | {% raw %}<div class="notification is-warning">{% endraw %} |
Icarus 主题以白色的简洁为主,但有时候我们希望在文章中用特别的样式注明一些内容,markdown 语法就不够用了,所以在此分享一下我的高级玩法。
1 | {% raw %}<div class="notification is-danger">{% endraw %} |
1 | {% raw %}<article class="message is-info"><div class="message-body">{% endraw %} |
1 | {% raw %}<article class="message is-success"><div class="message-body">{% endraw %} |
1 | {% raw %}<article class="message is-warning"><div class="message-body">{% endraw %} |
1 | {% raw %}<article class="message is-danger"><div class="message-body">{% endraw %} |
1 | {% raw %}<article class="message is-info"><div class="message-header">{% endraw %} |
1 | ``` js 点击展开代码 >folded |
iMaeGoo 出自独立游戏 World of Goo 里小粘球的叫声,读作 /ɪ’mæɡu/ 不是爱妹狗啊,在家里电脑还是个大头(CRT)的时候就在玩了,其实头像也是在当时设定的,一直沿用至今。找不到女朋友誓不改头像
1 | {% raw %} |
我们知道 Hexo 用 <!-- more -->
可以分隔简介和正文部分,但这样简介也会在正文中出现,如果我们不想让简介部分出现在正文呢?
1 | 这里的内容会出现在 **简介和正文** |
1 | <a class="tag is-dark is-medium" href="https://www.vecteezy.com/free-vector/vector-landscape" target="_blank"> |
这就是关于 Icarus 的高级玩法了,大家有什么想法呢,欢迎在评论区告诉小编一起讨论哦!(不是
]]>阅读模块的 README 之后,我按照 Quick start 一模一样地配置了相应的文件
You should create a site specific services.yml (monolog.services.yml for example) in the same
folder of your settings.php and then add this line to settings.php itself:
1 | $settings['container_yamls'][] = 'sites/default/monolog.services.yml'; |
The simplest configuration that allows Monolog to log to a rotating file might be:
1 | parameters: |
解压模块到 drupal/modules/contrib/monolog
,用 drush en monolog
命令启用,却遇到了报错。
1 | The service "monolog.handler.rotating_file" has a dependency on a non-existent parameter "monolog.level.debug". |
原因在于,”monolog.level.debug” 是在 monolog 的 monolog.services.yml 里面定义的,未开启 monolog 时,这个常量不存在,而这个常量不存在,setting.php 就会报错,setting.php 报错,就无法开启 monolog …… 这是一个死循环。
解决办法1:用 try 包裹 setting.php 中引入 monolog.services.yml 的行。
1 | try { |
解决办法2:在自己的 monolog.services.yml 中同样声明 monolog.level.debug。
1 | parameters: |
只需给 handler 配置 formatter
1 | parameters: |
只需用 StreamHandler 输出到 php://stdout
1 | services: |
看了前两个你也会发现,这里面的 arguments
是啥?只见其值不见其名,它是什么意思?
我们可以理解 handler
控制日志输出的方式,不仅支持写到文件、控制台,甚至可以配置发送邮件,arguments
则是 handler
的参数。
关于有哪些 handler
,可以到 02-handlers-formatters-processors 查看;
关于每一种 handler
需要怎么配置 arguments
,可以到这个页面搜索 handler 的名字,看 __construct
前的注释。
processor
控制日志包含的内容,有哪些 processor
也需要在模块的代码里看。https://git.drupalcode.org/project/monolog/-/tree/8.x-1.x/src%2FLogger%2FProcessor
强烈吐槽:为什么我需要看代码来研究一个 “世界上最好的日志插件” 怎么用……
很多时候我们需要把不同级别的 LOG 打到不同的地方去,一开始我试着这样配
1 | services: |
发现一个问题,info.log 不仅包含了 INFO,还包含了所有级别高于 INFO(如 WARN, ERROR)的日志,我不想把 ERROR 打在 info.log 里,怎么办?
我先提交了一个 issue Is it possible to set maxium logging level?
后来经过 Will 巨佬指点,可以利用冒泡参数实现这样的需求。
1 | /** |
$bubble
默认为 TRUE。我们首先配置两个 handler,一个打 INFO,一个打 ERROR,然后将 ERROR handler 的 $bubble
设置为 FALSE,阻止其向上一个 INFO handler 冒泡,这样,当 INFO log 来时,不会走 ERROR handler,而经由 INFO handler 打出,当 ERROR log 来时,会先由 ERROR handler 打出,然后不会冒泡到 INFO handler,达到目的。像这样——
1 | parameters: |
如果你和我一样只是想在 1.3.10 原版的基础上增加昵称和邮箱的防空验证,可以直接下划到结尾部分,跳过前半部分的过程记录。
最近经受匿名评论的困扰,计划禁止匿名评论。还有一个原因是《网信办:网站不得向未实名认证的用户提供跟帖评论服务》,咱小小博客也是备过案的(能用国内 CDN 加速太香了),应该注意一下是不是?
很遗憾,Valine 作者不计划添加这一功能!这让我一度想要换评论系统了……先不谈数据转移,我对比了一下其他评论系统——
昨天发现 Valine 1.4 发布,有几个新特性挺喜欢,打算升级,想起这茬,干脆一起把防空校验加上吧!
1 | const requiredField = ['nick', 'mail']; |
这只是关键部分,完整 diff 详见:https://github.com/imaegoo/Valine/commit/c18515593f16454833c757c91540ef5af0770fa5
后台验证暂时没研究出,LeanCloud 支持字段设置 “不能为空”,但依然不能阻止插入空字符串,文档中还没查到怎么给字符串验证。
写完了编译试一下,就掉进坑里了,Valine 1.4.4 版本通过源码 build 出的 js 报错 Cannot redefine property: applicationId,需要看看作者怎么说。
无奈切回 1.3.10,加上自己的代码,测试一下,成功!
测通之后已经 26:30 了,教程晚会再写吧,目前还有后台验证和 1.4 升级的坑没有解决,如果你喜欢,欢迎留言,教程更新后我会邮件告知 o( ̄▽ ̄)ブ
遗憾地,@MHuiG 告知我 1.4.4 并没有开源。同日,作者也在 README 中提到:
由于某些原因,
src目录
将从v1.4.0
后暂停更新.
For some reason, thesrc directory
will be suspended from updating afterv1.4.0
.
所以暂时放弃升级 1.4 的计划,也就不再对 1.4 增加判空功能了。
我修改过的 Valine 在 Github 开源:
https://github.com/imaegoo/Valine/tree/imaegoo/1.3.10
如果你用的是 Icarus 3.0 主题,你可以创建 themes/icarus/layout/comment/valine.jsx
来覆盖原版主题的 Valine 组件。
1 | /** |
如果你用的是其他主题,你可以自己查找 Valine.min.js 的引入位置,替换成:https://cdn.jsdelivr.net/gh/imaegoo/Valine@1.3.10.1/dist/Valine.min.js
在阅读这一部分前,可以先参考文章 HTML中嵌入SVG图片的N种方式,了解一下不同的 SVG 嵌入页面的方式。
缺点 | 解决方案 |
---|---|
如果将 SVG 放在静态资源目录,通过路径引用至页面,SVG 将造成额外的 HTTP 请求 | 在 HTML 中内嵌 <svg> 标签 |
如果在 HTML 中内嵌 <svg> 标签,HTML 会显得杂乱且无法复用 | 使用 SVG Inline Loader for Webpack 可以用 require 的方式向 HTML 插入 SVG |
图标本身带的颜色(类似 fill="#ccc" )无法覆盖 | 移除 SVG 本身的颜色。使用 SVG Inline Loader for Webpack 的 removingTagAttrs 选项,可以在打包时批量去除图标本身的颜色,再通过 CSS fill 覆盖颜色 |
缺点 | 解决方案 |
---|---|
因为字体图标本身是一个字符,所以会受到系统级反锯齿(如 ClearType 和 Retina)影响,导致本来锐利的小尺寸的图标边缘不锐利 | 使用 font-smooth 样式控制图标的反锯齿,在 Chrome 下测试没有成功,未找到更好的解决办法 |
当遇到网络较差,或者用户使用了屏蔽网页字体的插件时,图标会变成口口 | 在字体文件加载完成之前尝试隐藏所有图标 |
无法显示彩色图标 | 目前发现有网站是把彩色图标拆分成单色图标,再叠加显示,用 SVG 显然更方便 |
定位不准 | 这个大多数前端开发应该都有感触,典型就是复选框和文字标签对不齐,要检查图标的 CSS line-height ,vertical-align ,letter-spacing ,word-spacing ,display , 寻找对不齐的原因 |
维护(增加、删除图标)困难 | 使用阿里的 iconfont 服务来管理字体图标是很好的办法 |
对屏幕阅读器等辅助功能不友好 | 需要做适配,可以参考 Bulletproof Accessible Icon Fonts |
原主题
Icarus 夜间模式(实验中)
如何给 Icarus 增加夜间模式
夜间模式单独提取的代码目前已经更新,支持 Icarus 3.0.0,有需要的朋友欢迎 checkout。
分支:https://github.com/imaegoo/hexo-theme-icarus/tree/night3
提交:https://github.com/imaegoo/hexo-theme-icarus/commit/fc3d016ae1c999347bd9ecbf3cc656e1382db06d
1 | cd theme/icarus |
中文姓名非常多样化,想要真正区别出姓名和非姓名非常困难,但在这篇文章中,作为前提,我们认为合法的中文姓名由 1~10 个中文字符组成。
知道了这个前提,容易得出 JS 的正则表达式——
1 | /^([\u4e00-\u9fa5]{1,10})$/ |
通俗解释:
^
匹配开头;\u4e00
代表第一个汉字“一”;\u9fa5
代表最后一个汉字“龥”;[\u4e00-\u9fa5]
匹配一个中文字符;{1,10}
这个中文字符出现 1 到 10 次;$
匹配结尾。
测试一下——
1 | const CHINESE_NAME_PATTERN = /^([\u4e00-\u9fa5]{1,10})$/; |
PHP 中不认 \u4e00
,需要稍微变换一下语法——
1 |
|
结尾的 u 是什么意思?官方文档 中有描述:
u (PCRE_UTF8)
此修正符打开一个与 perl 不兼容的附加功能。 模式和目标字符串都被认为是 utf-8 的。 无效的目标字符串会导致 preg_* 函数什么都匹配不到; 无效的模式字符串会导致 E_WARNING 级别的错误。 PHP 5.3.4 后,5字节和6字节的 UTF-8 字符序列被考虑为无效(resp. PCRE 7.3 2007-08-28)。 以前就被认为是无效的 UTF-8。
SQL 中也无法直接写 Unicode 转义 \u4e00
,需要使用 HEX 将汉字转哈希之后,再匹配汉字的哈希值。
汉字的 HEX 范围:E4B880
~ E9BEA5
,所以可以用 e[4-9][0-9a-f]{4}
代表一个中文字符。
1 | SELECT HEX('一'); # 'E4B880' |
细心的读者可能会发现,HEX 输出的是大写字母 E
,为什么匹配的时候用的是小写字母 e
?其实这也是 MySQL 正则与 JS 正则的不同之一。
SQL 中,REGEXP
是不区分大小写匹配,REGEXP BINARY
是区分大小写匹配。
JS 中,/.../
是区分大小写匹配,/.../i
是不区分大小写匹配。
根据 README 描述,这个库似乎只支持 256-bit 的密钥,请使用 AES 密钥在线生成器 生成 256-bit 的密钥使用。
1 | use Defuse\Crypto\Crypto; |
1 | { |
来自 Drupal module - Real AES 的源码,有修改。
]]>1 | function keygen($length) { |
From: https://github.com/gladchinda/keygen-php/blob/master/src/Keygen/Generators/TokenGenerator.php
我和同事的两套本地开发环境,相同的一段返回随机验证码图片的代码,验证码代码参考的是 php实现的Captcha验证码类实例 里的代码。在同事的电脑上调用,出来的是裂开的图片,在我的电脑上调用,出来的就是正常的图片,这是为什么呢?解决这个问题花费了三四个小时,记录一下过程。
因为代码上没有区别,所以开始怀疑环境问题,两台开发机都是相同型号,配置也相同,PHP 运行在 docker 容器下,检查 PHP 版本相同。
查了一下 PHP 文档,怀疑可能是因为什么特性没有启用,测试以下代码:
1 |
|
测试结果 imagetypes() & IMG_PNG
的值大于零,看起来两个环境都是支持 PNG 图的。
比较两台电脑生成的图片,首先用 Notepad++ 打开损坏的图片,发现文件头尾都是正常的。
为了减少干扰因素,我注释掉了随机生成验证码的部分,让两个环境都生成相同的空白图片,然后用 UltraEdit 或其他 16 进制文件编辑器打开。
这时候我才发现了区别,损坏图片开头多出了3个字节,EF BB BF,即我们常说的 UTF-8 BOM。
有了线索就上网查,查到了另一博客 东风无力百花残 的文章 PHP文件头BOM头问题
我刚因为一个愚蠢的问题而损失了大约4个小时。我在本地服务器上的图像以某种方式被损坏,因此没有显示在浏览器中。经过多次环顾和测试,包括多次在我的计算机上重新安装 apache,我将问题追溯到包含的文件。
没有问题不是空白,而是 UTF BOM 编码字符在我的一个未被引用的文件的开头…
所以,当心你的包含文件!
确保它们未在 UTF 中编码,或者在没有物料清单的 UTF 中进行编码。
希望它能省下别人的时间。
好的,感谢……等等,我们不太一样,我们用的是 Symfony HttpFoundation 模块做的 API,controller 也都是不包含 BOM 头的呀……
我也不是很懂 PHP,继续查,又查到了一个 StackOverflow 上的问题 Symfony2 Remove UTF-8 BOM from controller responses
好的,感谢……等等,看回复,最后他是排除了这和 Symfony 的关系,并没有给出解决方案……
这个文件头到底该怎么去掉啊……
我在本地试着给 API 的入口点 index.php 文件改成了 UTF-8 With BOM 编码,保持之后,“成功” 把图片搞裂了。
激动地去找同事检查她的 index.php,咦,并没有 BOM。
线索断了……
最后还是同事自己找到的解决方案,只要换一个思路,我们找不到 BOM 是在何处加上的,也无法保证部署后文件没有 BOM,那就在返回图片流之前,清空缓冲区。
1 | ob_end_clean(); |
问题立即得到解决。
最后还是没想出来 BOM 在哪里出来的……
]]>3.0.0-beta.1
一路使用到现在,把自己的使用经验分享一下。由于主题作者换掉了 ejs 语言,全部重写了一遍,迁移这块的难度是最大的。
拉 dev 分支,冲突实在是太多了,我的办法是,把在旧版上的魔改的整个 diff 导出,然后直接从 dev 签出一个新的分支,参考 diff 对每个文件都重新修改,花了不到2个小时搞定。
主题中部分可重用的 JS 和 JSX 代码已经被移到另一个项目 hexo-component-inferno
中,我们如何对这些组件魔改?此时要分2种情况——
直接从 hexo-component-inferno / src / view 把需要修改的 JSX 复制到主题目录下的 layout/widget
,再进行魔改即可。
例如:我需要修改 subscribe_email widget,在组件根 DOM 上加一个 id 以实现 live2d 交互,需要复制
hexo-component-inferno/src/view/widget/subscribe_email.jsx
到themes/icarus/layout/widget/subscribe_email.jsx
,再进行修改。
当然,如果你有自己写的 widget,也可以统统丢到 layout/widget
里去。
需要全局搜索引用处,修改引用路径为主题路径下改好的文件。
例如:我需要修改
paginator.jsx
以改变分页的 delta 值,可以复制hexo-component-inferno/src/view/misc/paginator.jsx
到themes/icarus/layout/misc/paginator.jsx
,再进行魔改,修改完成后,需要全局搜索hexo-component-inferno/lib/view/misc/paginator
并替换为./misc/paginator
(注意,这里我写的是相对路径,请在替换后确认每处引用的相对路径正确)。
1 | - const Paginator = require('hexo-component-inferno/lib/view/misc/paginator'); |
不建议直接修改原来的 CSS 文件,而是覆盖样式,由于 3.0 中已经对 CSS 代码进行细分,建议把魔改的 CSS 也抽成单独的文件,方便管理。
1 | icarus |
自己建立的 styl 文件,需要在 style.styl
中引入。
1 | @import "imaegoo" |
我曾经使用 gulp 来压缩 Hexo 生成的静态 HTML, CSS, JS 文件,但 3.0 对所有的 JS 使用了 ES6 重写,这造成了压缩插件不工作。
我尝试过把所有使用 ES6 语法的地方手工改回 ES5 语法,但最终放弃了,为什么要倒退呢?这反倒会增加未来升级的难度。
我放弃了对存在 ES6 的 JS 压缩,把它们全部丢进忽略列表吧!
1 | // 压缩 js 文件 |
之后研究中发现了 Azure 提供的应用服务还挺好用的,当然重点是——可以白嫖!
免费套餐当然是有限制的——
我们可以在上面部署 .Net Core, ASP.NET, Java, Node.js, PHP, Python, Ruby 语言的项目。
之前有访问过别人的 PyOne,发现下载速度还挺快,就一直想用 OneDrive 搭建一个自己的网盘,机会来了。
主流的 OneDrive 第三方 Directory Index,有老牌的 oneindex,还有后起之秀 PyOne 和 OLAINDEX,虽然 Azure 的 PHP 环境可以自动识别 composer 安装依赖,也支持执行部署脚本、执行 php 命令,但是由于 PyOne 还要依赖 Python 环境,OLAINDEX 还要依赖 Nginx,别想了,搭建不了。
当我尝试在 Azure 应用服务上面部署 OLAINDEX 时,在执行安装脚本
php artisan od:install
时出错,遇到的错误是 SQLiteGeneral error: 5 database is locked
,由于完全不会 PHP,就放弃了。
好了,就决定是 OneIndex 了!高手看到这里基本就可以自己去尝试了,下面是我的步骤。
申请一个国际版 Azure 的体验账户,需要注意 Azure 不审核国内用户申请国际账户,国内放心申请。鉴于每人有一次限时 1 个月 200 刀的体验额度的机会,请想好了再申请。
步骤略。
进入建好的应用服务,选择左侧的“部署中心”。
有许多种部署方式可以选择,FTP 方式非常慢,GitHub 方式需要授权,建议选择本地 Git 部署。
接下来选择选择应用服务生成服务
,因为我们没有部署脚本,用不到 Azure Pipelines。
部署设置完成后,点击上边的“部署凭据”,之后的步骤会需要这里的 Git URL、用户名、密码。
在本地执行命令来部署:
1 | git clone https://github.com/donwa/oneindex.git |
输入上一步中的用户名和密码,即可开始部署。
访问应用地址,如 https://imaegoo.azurewebsites.net,根据安装向导配置应用ID和机密,部署完成!
]]>这个提示在打开浏览器几秒之后出现,并夺走窗口焦点,很是烦人,如何屏蔽呢?
搜索之后,发现网友小茗同学给出了一个修改 dll 文件的方案,方案危险系数较高,并且会随着 Chrome 更新而失效,有没有更好的办法呢?
我使用的火绒杀毒提供了一个弹窗拦截工具,很好地解决了这个问题。
这样一来,警告没有消失,但每次都会被自动关闭,安全有效。
谷歌访问助手项目的 Wiki 中介绍过如何将第三方插件加入白名单,这种方法解决了安装之后无法启用第三方插件的问题,但是,经测试仍然会有“请停用”警告弹窗,有兴趣研究的可以看看。
https://github.com/haotian-wang/google-access-helper/wiki/Installation-Guide#%E6%96%B9%E6%B3%952%E7%9B%B4%E6%8E%A5%E5%AE%89%E8%A3%85crx%E6%96%87%E4%BB%B6
已安装 Vue 脚手架
1 | npm install -g @vue/cli |
找不到 vue-cli-service
命令
1 | 'vue-cli-service' is not recognized as an internal or external command, operable program or batch file. |
经过搜索,发现这个问题只在 Windows 下存在。
装了脚手架应该会在 node 目录产生 vue-cli-service.cmd
的文件,实际没有产生,不过在全局 node_modules
下是有的。
有说清理 node_modules
重新安装可以解决的,试了不管用,全局卸载脚手架重新安装也不管用,就算管用也比较麻烦,于是我找到了几个间接使用方法——
在 package.json
中配置启动命令
1 | { |
然后使用 npm run serve
来代替 vue-cli-service serve
命令前加 npx,如
1 | npx vue-cli-service serve |
更多关于 npx 介绍见——https://www.ruanyifeng.com/blog/2019/02/npx.html
1 | vue ui |
$t
的报错。1 | <p>{{ $t('message.hello' }}</p> |
1 | TypeError: _vm.$t is not a function |
Vue 节点上没有 $t,先尝试挂载?
1 | import VueI18n from 'vue-i18n' |
结果会遇到另一个相似的错误。
1 | TypeError: Cannot read property '_t' of undefined |
我们的 Test Case 不需要测到国际化字符串,那就 mock 一个 $t 好了。
1 | shallowMount(Component, { |
测试就通过了。
相关插件版本号:
1 | { |
当前 URL:http://localhost/home?keyword=example
1 | this.$router.replace({ query: { ...this.$route.query, code: '1' } }) |
最终 URL:http://localhost/home?keyword=example&code=1
我所使用的 Vue Router 版本为 3.0.3,删除参数比较麻烦。
当前 URL:http://localhost/home?keyword=example&code=1
1 | delete this.$route.query.code |
1 | let newQuery = JSON.parse(JSON.stringify(this.$route.query)) // 深拷贝 |
最终 URL:http://localhost/home?keyword=example
使用 this.$router.replace()
以及 this.$router.push()
时,地址栏变化是有延后的,且这个延后无法通过 this.$nextTick()
预测。
以下场景:
微信 OAuth 回跳到我们的页面时,会在 URL 追加 code 参数用于认证,我们成功获得 code 后想要从地址栏去掉它,同时还要配置微信 JS SDK。
配置微信 JS SDK 需要当前页面地址(window.location.href.split('#')[0]
),而我们去掉 code 会导致地址改变。
地址栏实际改变完成的时间是不可预测的,而配置微信 JS SDK 有成功回调,所以需要先配置微信 JS SDK,再处理地址栏。
参考资料:https://stackoverflow.com/questions/48700584/vuejs-how-to-remove-parameter-from-url
]]>这次是用 Vue 做了一个编号抽奖,一个转盘抽奖,放在一起,练手。
预览:http://lottery.imaegoo.com/
编号抽奖实现起来非常简单,存一个号码池,存一个抽奖历史,从号码池中过滤掉已中奖的号码,从剩下的号码随机出一个就可以了。
1 | <template> |
转盘抽奖稍微复杂一点:
transform
上transition: transform 5s;
做完之后发现也不是很难。
1 | <template> |
指针 arrow.png
和转盘 wheel.png
两张图片可以在 https://github.com/imaegoo/lottery/tree/zhengzhou/src/assets 找到。
反正只有4个页面,直接自己写一个 tab 切换,没有引入 vue-router。
功能太简单也用不到,只用了一个 Bulma。
啊~ 轻量又好用的 Bulma~
源码放在了 https://github.com/imaegoo/lottery 上面。
设计、切图、编码、测试总共花了6小时,嗯,挺简单的。
]]>Alt
+ Shift
+ F10
来自动导包,在 VS Code 中怎么操作呢?快捷键是 Ctrl
+ .
(句点)。
坑:必须在英文状态下按快捷键才能起作用。
如果你还没有安装安装并配置 VS Code 的 csharp 插件,这个快捷键可能不起作用。
在 Extensions 页搜索安装 C#
重新打开项目,会弹出提示,选择是
等待 Output 输出 Finished
来源:
https://stackoverflow.com/questions/148977/visual-studio-keyboard-shortcut-to-automatically-add-the-needed-using-statemen
https://docs.microsoft.com/en-us/dotnet/core/tutorials/with-visual-studio-code
不过今天看 Ant Design Pro 官网的 footer 的时候发现了 Netlify 这个东西,试了以后,强烈安利!!!
来到它的首页,里面有这么几段话——
大字:
在几秒钟内部署您的网站*
小字:
*不,这里没有陷阱。
真的只需点击几下。
嗯……嗯?哼哼……有免费套餐,试试吧!
然后构建就启动了,1分钟后我的站点就到了 Netlify 上。
当时我的表情是 (⊙o⊙)?
我连部署命令都没打;
我连环境都没提供;
我甚至全程没有摸一下键盘
……(你要问我注册登录不摸键盘?真就没摸,GitHub 是已登录的状态,点一下授权按钮就登录了。)
敢情 hexo 的部署配置,Azure 的 CICD 都白写了呗?
……
😓,流批……
这个网站还支持绑定域名,自动申请 HTTPS,配 Web Hook(就不用手动点部署了),还有很多很多真 · 自动化的功能,大家一起发掘吧!
]]>此篇针对 Icarus 2 版本,Icarus 3 请参考:Icarus 夜间模式支持 3.0 了
This extension is NOT FULLY TESTED, so it may not fully cover the theme styles, if you find something wrong (such as bright things in night mode), please report it in this issue, do not open new issue.
night
branch from imaegoo/hexo-theme-icarus into your icarus theme folder, or dowmload zip.themes/icarus/_config.yml
.1 | logo: |
night
分支(imaegoo/hexo-theme-icarus)合并到你的主题分支中。如果你不懂,并且你对主题没有自己修改,直接下载修改好压缩包。themes/icarus/_config.yml
中配置。1 | logo: |
If you want to customize your theme, you can modify night mode
part in themes/icarus/source/css/style.styl
.
Universe background from https://github.com/fan-lv/Fan
]]>上网对比了一下,换成了网易的,结果设置MX记录验证过不去,让等48小时,等不了,再换。
现在换到了俄罗斯的 Yandex,初期体验还不错。
优点:
缺点:
……过程就不细说了,登录 https://connect.yandex.ru/pdd/ 按步骤申请就可以,需要开着在线翻译面对随时可能出现的俄文。
]]>List 组件通过
loading
和finished
两个变量控制加载状态,当组件滚动到底部时,会触发load
事件并将loading
设置成true
。此时可以发起异步操作并更新数据,数据更新完毕后,将loading
设置成false
即可。若数据已全部加载完毕,则直接将finished
设置成true
即可。
实际应用中发现,即使内部元素已经填满一整屏,仍然会触发加载,直到我模拟的20多页全部加载完才停下来。
我没有给这个问题写专门的 CodePen demo,比较麻烦,碰到的人也不一定多。
van-list 会在内容之后增加一个 placeholder,通过 placeholder 的位置判断内容是否已填充满屏。
van-list 本身为 flex 布局时,flex-direction 必须是 column(或 column-reverse)。
首先我的用法是这样的:
1 | <van-list> <!-- flex --> |
首先看文档,英文文档没有提到,但中文文档有以下一段话:
使用 float 布局后一直触发加载?
若 List 的内容使用了 float 布局,可以在容器上添加van-clearfix类名来清除浮动,使得 List 能正确判断元素位置
检查了一下,我没有在使用 float 布局呀。
那看一下Vant源码,主要看Vant是如何判断页面何时去加载的:
1 | this.$nextTick(() => { |
scrollerRect
是滚动区域的位置,通过 debug 看到获取到的值没有问题,但 placeholderRect
的值一直都是同一个值,导致 isReachEdge
一直是 true
。
进一步 inspect 页面元素,发现这个 placeholder 的位置在这里:
1 | <van-list> |
placeholder 是一个没有大小的 div,由于 van-list 是 flex 横向布局,placeholder 自然地落在了 van-grid 的右边,这时不管 van-grid 怎么高,placeholder 的位置都不变了。
知道了问题所在,我们在 van-list 元素上增加了 flex-direction: column;
成功地解决了问题。
许久没再打开过的QQ空间突然有了提示,打开看到是母亲在翻我的软件相册,里面是些高中做出来的东西。
学业那么紧张的情况下,有时间接触手机电脑,甚至还写代码,在我们那个年代,绝对不是随便哪个学生都有的经历。
有初中时候写收菜脚本的基础,我对逻辑有了一定的理解并逐渐着迷,但又没有系统的教学,写出来的东西甚是粗糙。那时候学习 VB 仅仅是看一张名为开天辟地的电脑速成光盘,早期甚至都没有宽带网。
不知道如何解析 HTML,就用字符串查找函数;
不知道如何模块化编程,就一个文件写 800 多行;
不知道如何定位异常,就给每一行代码开头加行号;
不知道怎么做安装程序,就写 bat 脚本用 RAR 打自解压包;
不知道怎么读写配置文件,就用基本输入输出 txt;
甚至一开始连缩进都不懂,代码直上直下的……
虽然走过这么多的弯路,还影响了高中学习险些没有考上本科,但收获了许多课堂里学不来的东西。
这月初的时候,我在整理一块老硬盘,把高中写的 班班通助手 和 班班通助手2.0 传到了 Github 上保存。我终究还是怕在硬盘里哪一天它就那样丢失了。
在 失去理智注意力涣散 的时候,想想曾经为之着迷的自己,至少还是很励志的。
来看看当时的自己给班班通助手做的宣传PPT吧!
注:此处下载地址 wodemo.com 我的磨是当时比较流行的用于分享软件的网盘,和现在的蓝奏云差不多的性质,现在我的磨已经无法打开了。
UI 截图 ↓
还有另一个班的同学模仿做出来的 ↓
当时的电教柜是威科姆 VCOM 提供的触屏投影式电脑,所以对触屏优化就借鉴 Win8 ↓
为了分享到别的班,甚至做出了安装向导和设置向导 ↓
配套的小工具们 ↓
这是改了很多版越来越沙马特的 v1 版本 😂 ↓
当时的感想(817 行现在看好像不多也 😂) ↓
为了方便班里的小吧主同学管理贴吧做的 ↓
以及做了一半因为高考而夭折的 SNS 聚合软件 ↓
]]>通过向 body 添加名为 night
的 class 实现,状态记在浏览器 localstorage 中。
已知问题:
目前还没有做成插件,仅在自己的博客使用,后期如果有时间的话,会考虑做成 extension。
更新:已经发布了——
Icarus 2 请参考:如何给 Icarus 增加夜间模式
Icarus 3 请参考:Icarus 夜间模式支持 3.0 了
屏幕高度 < 左边栏的高度 < 内容的高度
时,滚动屏幕,左边栏会随着内容一同滚动,当滚动到左边栏底部时,左边栏会停止滚动,而内容会继续滚动。这种设计的优势在于,用户既能够滚动左边栏,又不会在左边栏不够长时,造成页面左侧大片空白的尴尬,这种布局模式,叫做 粘性布局(sticky)
。
粘性布局在元素满足显示条件时,表现与普通布局没什么不同,但当元素随着页面滚动而无法显示时,会转为 fixed
布局效果,主流浏览器已经全部支持粘性布局(IE不支持)。
通俗一点讲,类似于 Excel 中的“冻结窗格”。
绝大多数网上的教程材料都用 position: sticky; top: 0;
这样的组合来举例,但为了实现 CSDN 左边栏效果,position: sticky; bottom: 0;
似乎不能和想象一样的起作用。
position: fixed; bottom: 0;
样式,把左边栏定死,延时较为明显,快速上下滚动时能看到闪烁。position: sticky;
实现,通过 JS 计算 屏幕高度 - 左边栏高度
得到 top
的值,快速滚动时没有闪烁。position: sticky; bottom: 0;
不起作用后,上网搜索也并未查到结果。top: calc(100vh - height)
这样的句子…… 不管用。1 | // 仿 CSDN 左侧栏吸底效果,设置 position 为 sticky,top 为屏幕高度减去左侧栏高度,比 CSDN 的实现更简洁。 |
如果你也想用这段代码,别忘了把 .column-left
替换成你的粘性元素的选择器,并在那个元素上添加 position: sticky;
样式~
Windows 环境,缩放 100% 下,当 top
的值为非整数像素值时,Chrome 会有元素内字体模糊的情况,Firefox 和 Edge 没有问题,所以有必要对 top 取整确保字体清晰。
由于谷歌最近对 Chrome 地址栏改来改去,不同的版本需要对应不同的方法。
在浏览器输入 chrome://flags/
回车,找到 Omnibox UI Hide Steady-State URL Scheme and Trivial Subdomains
,设置为 Disabled,然后重启浏览器。
谷歌从 flag 页面砍掉了这个设置,但 flag 还是存在的。
打开 chrome://flags/,78版本已经找不到 omnibox-ui-hide-steady-state-url-scheme
和 omnibox-ui-hide-steady-state-url-trivial-subdomains
了。
按 F12 打开 Console,执行以下命令,然后重启 Chrome。
1 | [ |
代码中 @2
对应的是 Disabled。@0
和 @1
分别对应 Default 和 Enabled。
测试有效的版本:78.0.3904.97
方法来源:ysc3839(https://www.v2ex.com/t/613776)
谷歌彻底砍掉了这两个 flag……
现在安装插件是唯一方法,如果你能够访问 Chrome 网上应用店的话,安装这个插件,无需配置即可显示完整地址:
https://chrome.google.com/webstore/detail/suspicious-site-reporter/jknemblkbdhdcpllfgbfekkdciegfboi
方法来源:MaiKuraki(https://www.v2ex.com/t/588136)
如果是 Windows 系统,也可以换用 Chromium 内核的 Edge 浏览器,我已经完全爱上 Edge 啦!
据IT之家报导,谷歌决定“使URL更易于阅读和理解,并消除对可注册域的干扰”,在Chromium Gerrit中新提交了一个flag标志,未来可在 chrome://flags#context-menu-show-full-urls
中设置开启,届时Chrome浏览器地址栏便可显示完整URL。
嗯,砍了再加回来,绝世好活!
我并没有下载 Chromium 测试这个 flag,未来推出有这个 flag 的正式版后,我可能会会更新这篇博文。
]]>docker-compose up -d
,重启命令 docker-compose restart
,关键 log:
1 | InnoDB: Assertion failure in file /bitnami/blacksmith-sandox/mariadb-10.2.28/storage/innobase/dict/dict0dict.cc line 1467 |
详细的 stdout 如下——
1 | 03:20:42.43 Welcome to the Bitnami mariadb container |
1 | 2019-11-15 15:08:01 140200219911936 [Note] /opt/bitnami/mariadb/sbin/mysqld (initiated by: unknown): Normal shutdown |
1 | 16:16:36.31 Welcome to the Bitnami mariadb container |
官网下载安装,比我的新即可,安装路径自选。
新建文件夹并创建 Vagrantfile 放在里面,我配置的环境是 Ubuntu 16.04,内存8G,可以换成自己熟悉的环境。
映射端口80,443(Web),3306(数据库),9200,9300(搜索引擎)。
1 | Vagrant.configure("2") do |config| |
在 Vagrantfile
所在目录执行
1 | vagrant up |
1 | curl -fsSL https://get.docker.com -o get-docker.sh |
1 | sudo usermod -aG docker $USER |
修改 VMA(虚拟内存区域)数值以保证 Elastic Search 可以顺利启动
1 | sudo sysctl -w vm.max_map_count=262144 |
使用官方一键部署脚本部署。
1 | curl -sSL https://raw.githubusercontent.com/bitnami/bitnami-docker-magento/master/docker-compose.yml > docker-compose.yml |
1 | docker ps -a |
在 Windows 中打开 http://127.0.0.1,检查是否能够正常访问。
默认后台:http://127.0.0.1/index.php/admin/
默认用户:user
默认密码:bitnami1
docker logs [容器ID]
查看 log1 | let obj = { id: 1, title: "1" } |
1 | let obj = { |
1 | let arr = [1, 2, 3] |
1 | let arr = [ |
1 | let arr = [ |
不考虑性能的情况下,JSON.parse(JSON.stringify(value))
是最简最万能的拷贝。
需要注意,不要直接在JS中操作一个Vue data对象中不存在的属性,如果同时有通过v-model
绑定到该对象的不存在的属性时,会出现诡异的行为表现,console
中不会报出任何 warn
或 error
。
需求是,实现三个复选框,第一个复选框初始为选中状态,一开始写出来是这样的——
1 | <div id="app" style="margin: 10px;"> |
1 | new Vue({ |
试下效果:
See the Pen vue-v-model-not-work by iMaeGoo (@iMaeGoo) on CodePen.
复选框a的表现显然是异常的,点击不能成功地切换选中状态,而在点击之后再点击其他复选框,才会“有延迟地”切换状态。
尝试在created
方法的末尾打印出this.checkboxes[0]
——
发现 id
和 title
都变成了 getter/setter 的形式,而 selected 仍然是独立的属性。
后续查询发现,Vue 官方文档 - 深入响应式原理 的第一段话是——
当你把一个普通的 JavaScript 对象传入 Vue 实例作为
data
选项,Vue 将遍历此对象所有的属性,并使用Object.defineProperty
把这些属性全部转为getter/setter
。Object.defineProperty
是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
在 created
方法中,我尝试直接对 Vue data 对象中的属性操作,而 v-model
需要使用 getter/setter
操作,二者即产生了冲突。
在 data 中添加 selected 属性,即使初值为undefined
或者null
,也能够让 Vue 正确识别所有对象属性。
1 | data () { |
在JS中操作原本不存在的属性时,使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性
1 | created () { |
早在之前,1就已经可以通过 CSS3 filter
属性实现,而2一直没有一个好的解决方案。对1的运用,也可以达到2的效果,通过模糊图片的一部分,就可以实现类似 bilibili 导航栏的模糊背景效果 ↓
这样实现的前提是,我们的背景是一个静态的,单一的图片,那么如果我们需要模糊的背景比较复杂呢?仔细观察QQ右栏的标题栏,和下方的应用 Dock,都是 iOS 常见的毛玻璃叠加层效果 ↓
显然模糊元素本身并不能解决所有场景的问题。
为了能够实现类 iOS 的毛玻璃,我发现了两种方式——
稍微研究就能发现,B站导航条的模糊,是用 两个相同的图片,以相同的坐标显示并叠加,再模糊上层的图片 实现的,那么同理,我们如果把整个页面的节点都复制一份,就能对局部模糊了。
第一步,将页面主体内容clone到navbar中,然后使用css3 -webkit-filter滤镜对内容做高斯模糊。
第二步,监听页面滚动事件,计算出scrollTop,将navbar中的内容做同步滚动,同步滚动使用的方法是transform下面的translateY样式,对Y轴做同步偏移。
原文:https://www.jianshu.com/p/e65ae2fd8aea
源码:https://github.com/LucienYang/blur_nav
Demo:https://lucienyang.github.io/blur_nav/
要完整地复制页面元素,显而,性能会不好,这种方法仅适用于元素较少的网站,且实现比较复杂。
但兼容性还是比方法2好的,而且……在没有方法2的情况下,能想到这个办法的人,真是天才……
在浏览MIUI11官网时,无意发现了其导航栏的毛玻璃效果——
F12一下,找到了这个还不普及的 CSS 属性——“backdrop-filter”。
这是一个实验中的功能,Firefox 完全不支持,较旧的 Chrome 中需要在 flag 中手动开启,好消息是新版的 Chrome 已经默认支持了,让我们看到这个属性的兼容性会越来越高。
backdrop-filter CSS 属性可以让你为一个元素后面区域添加图形效果(如模糊或颜色偏移)。因为它适用于元素背后的所有元素,为了看到效果,必须使元素或其背景至少部分透明。
能够完美解决“模糊元素后面的内容”的需求,但目前兼容性欠佳,在本人的测试下:
封面来源(Cover source):P站 / 针眼kyoeye / 希儿希儿希儿
武神千万位,希儿第一位
丽塔再插队,策划两行泪
EFK不是一个软件,而是一套解决方案,并且都是开源软件,其中 ELasticsearch
负责日志保存和搜索,FileBeat
负责收集日志,Kibana
负责界面。
Elasticsearch
、Logstash
、Redis
等平台。目前有3种思路:
以上的三种方案都存在阻力:
睡一觉之后产生了第4种方案:
4. 本地启动Elasticsearch、Kibana、Filebeat,循环执行rsync命令,SSH连接到服务器并把log增量同步到本地,本地Filebeat就可以畅快地读取了
Elasticsearch、Kibana由于资源消耗大,决定在Windows环境下启动
rsync 由于是 Linux 下的,只能在虚拟 Ubuntu 下启动
Filebeat 由于 log 在 Ubuntu 下,为了I/O效率,也在 Ubuntu 下启动
https://www.elastic.co/guide/en/kibana/current/windows.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started-install.html
请参考官方安装文档进行安装,本教程所用配置如下:
1 | network.host: [_local_, _site_] |
1 | server.port: 5601 |
这里使用Vagrant启动,安装Virtualbox和Vagrant,创建Vagrantfile如下
1 | Vagrant.configure("2") do |config| |
同目录下执行 vagrant up
,然后 vagrant ssh
连接上虚拟机。
1 | curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.3.2-amd64.deb |
1 | sudo vim /etc/filebeat/filebeat.yml |
这是common的配置,请按照自己项目的log格式配置相应的插件。10.0.2.2
代表宿主机,如果你用的也是Virtualbox + Vagrant,不要改动。
1 | filebeat.inputs: |
确保前面已经启动Elasticsearch和Kibana,然后启动Filebeat,sudo service filebeat start
首先服务器必须开启ssh_key登录,在Ubuntu下生成ssh配置到服务器的 authorized_keys
中。
执行 byobu
,这会开一个终端 session,在此执行的命令不会因为终端退出而终止。
快捷键 | 作用 |
---|---|
F2 | 新建一个窗口 |
F3 | 切换到上一个窗口 |
F4 | 切换到上一个窗口 |
F7 | 浏览当前窗口的历史打印信息 |
F6 | 让 byobu 到后台去 |
Ctrl + F6 | 关闭当前窗口 |
修改以下命令,并执行实现增量同步:
1 | while true;do rsync -rtv --include "**.log" --exclude "*.*" --append -e "ssh -p <服务器SSH端口号>" <服务器登录用户名>@<服务器地址>:/var/logs /home/vagrant;sleep 5;done; |
这个命令很长,所以给出命令解释:
while true
循环执行-rtv
r代表递归目录,t代表保留待同步文件的修改时间,v代表啰嗦模式,输出更多同步信息(可以-vv更啰嗦模式)--include "**.log" --exclude "*.*"
只同步log文件--append
增量同步,会比较文件大小,只同步多出来的部分-e "ssh -p <服务器SSH端口号>"
自定义SSH程序命令行,自定义端口/var/logs /home/vagrant
同步服务器的 /var/logs 目录到本地的 /home/vagrant 下sleep 5
同步每次结束后休息5秒,避免过多占用服务器带宽有兴趣的童鞋可以到这里学习rsync命令的更多用法:
https://www.cnblogs.com/f-ck-need-u/p/7221713.html
按F6把循环进程切到后台,稍等片刻后访问 http://localhost:5601/,看看能否查询到 log 了
如果历史log量很大,首次启动后会处理大量的log,短时间内查出大量的log是正常现象。
]]>在环境变量中添加:
打开VirtualBox,选择File->Preferences,修改Default Machine Folder:
]]>其实就是简单的 access.log 啦。
其实就是刚学习 Node.js 写的 demo 啦。
啊这是很简单你不要拆穿啦。
这是输出的 log 的样子,优化了可读性,时间、method、path、URL参数(Query)、请求头(Header)、请求体(Body)都详细记录了:
1 | info: 2019-07-25 18:04:36 |
依赖配置:
| 包 | 作用 |
| - | - | - |
| body-parser | 转换form表单、json等格式的请求体 |
| express | 启http服务 |
| moment | 时间格式化 |
| winston | 打log |
1 | { |
1 | const express = require('express') |
之后安装依赖,运行:
1 | npm install |
Spring Boot 也可以很简单实现,谁来写一下?
]]>1 | select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where REFERENCED_TABLE_NAME='[表名]' |
对多台云服务器进行流量分发的服务。负载均衡可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。
Amazon 提供的 ELB 服务包含三种类型:ALB, NLB, CLB。
Application Load Balancer 运行于请求级别(第 7 层),可根据请求的内容将流量路由至 EC2 实例、容器、IP 地址和 Lambda 函数等目标。Application Load Balancer 最适合 HTTP 和 HTTPS 流量的高级负载均衡,面向交付包括微服务和基于容器的应用程序在内的现代应用程序架构,提供高级请求路由功能。Application Load Balancer 通过确保始终使用最新的 SSL/TLS 密码和协议,简化并提高应用程序的安全性。
ABL于2016年8月发布,与现有的负载均衡器(OSI第4层TCP/UDP均衡器)不同,ALB将查看数据包并将其发送到正确的服务。单个ALB可以为许多后端服务平衡流量,而不是为每个服务运行弹性负载均衡器。例如,包含的URL /api
可以路由到与包含的URL /signup
不同的后端服务。
Network Load Balancer 网络负载均衡器运行于连接级别(第 4 层),可根据 IP 协议数据将连接路由至 Amazon Virtual Private Cloud (Amazon VPC) 内的不同目标(Amazon EC2 实例、微服务和容器)。网络负载均衡器最适合 TCP 流量的负载均衡,能够在保持超低延迟的同时每秒处理数百万个请求。网络负载均衡器还经过了优化,能够处理突发的和不稳定的流量模式,同时在每个可用区使用单个静态 IP 地址。它与其他流行的 AWS 服务集成,例如 Auto Scaling、Amazon EC2 Container Service (ECS)、Amazon CloudFormation 和 Amazon AWS Certificate Manager (ACM)。
Classic Load Balancer 同时运行于请求级别和连接级别,可在多个 Amazon EC2 实例之间提供基本的负载均衡。Classic Load Balancer 适用于在 EC2-Classic 网络内构建的应用程序。在使用 Virtual Private Cloud (VPC) 时,我们建议使用第 7 层 Application Load Balancer 和第 4 层网络负载均衡器。
使用 CLB 而不是 ALB 具有以下优势:
CLB速度慢于ALB。
封面来源: pixabay, free for commercial use.
]]>本文以初学者角度探讨四种Web攻击以及预防方式,是个人基于对多种Web漏洞的学习总结,不承诺内容规范。
跨站脚本(XSS,Cross Site Scripting)攻击是一种注入攻击,其恶意脚本被注入到其他可信网站中。当攻击者使用Web应用将恶意代码(通常以浏览器脚本的形式)发送给不同的最终用户时,就会发生XSS攻击。
允许这些攻击成功的缺陷非常普遍,并且发生在Web应用程序在其生成的输出中使用来自用户的输入而无需验证或编码它的任何地方。
攻击者可以使用XSS将恶意脚本发送给毫无戒心的用户。最终用户的浏览器无法知道该脚本不应该被信任,并将执行该脚本。
因为它认为脚本来自可靠来源,所以恶意脚本可以访问任何cookies,session tokens或浏览器保留并与该站点一起使用的其他敏感信息(比如document.cookie
)。这些脚本甚至可以重写HTML页面的内容(比如document.body.innerHTML=""
)。
XSS攻击通常可以分为两类:存储和反射。还有第三种不太知名的XSS攻击类型,称为基于DOM的XSS。
又名AKA Persistent,Type I
存储XSS通常在用户输入存储在目标服务器上时发生,例如在数据库,文件,论坛消息,访问日志等中,导致永久性的每次存储数据反射回响应文代码就会在浏览器中执行的一种XSS漏洞。
又名AKA Non-Persistent,Type II
当Web应用程序在错误消息,搜索结果或包含用户作为请求的一部分提供的部分或全部输入的任何其他响应中立即返回用户输入,导致代码在浏览器执行时,会发生反射的XSS。
又名AKA Type-0
Amit Klein,发表了关于这个问题的第一篇文章,基于DOM的XSS是XSS的一种形式,其中从源到接收的整个受污染的数据流在浏览器中发生,即数据的来源是在DOM中,接收器也在DOM中,数据流永远不会离开浏览器。例如,源(读取恶意数据)可以是页面的URL(例如,document.location.href),或者它可以是HTML的元素,而接收器是一个敏感的方法调用,导致执行恶意数据(例如document.write
)。
设想,某博客留言板允许插入第三方图片,输入图片URL后,会生成img标签:
1 | <img src="图片地址" /> |
普通图片地址:https://img.com/img.png
XSS地址:https://img.com/img.png" onload="javascript:alert(document.cookie);
文档呈现:
1 | <img src="https://img.com/img.png" onload="javascript:alert(document.cookie);" /> |
扩展:
多年来,大多数人认为这些(存储,反射,DOM)是三种不同类型的XSS,但实际上它们是重叠的。你可以同时拥有存储和反射的基于DOM的XSS。你也可以使用存储和反映的非基于DOM的XSS。所以为了帮助澄清,从2012年中开始,研究团体提出并开始使用新术语来帮助组织可能发生的XSS类型:
此处不讲解,参考:https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting
在实际项目中实施XSS攻击,获取用户cookie信息。
搭建Spring Boot Web项目,配置第三方服务以接收用户cookie信息。
1 | <img src='x' onerror='alert(document.cookie)'> |
XSS在属性中使用脚本
可以在不使用<script>
标记的情况下进行XSS攻击。其他标签将完全相同,例如:
1 | <body onload=alert(document.cookie)> |
XSS使用脚本通过编码的URI方案
如果我们需要隐藏Web应用程序过滤器,我们可能会尝试对字符串字符进行编码,例如:a=A (UTF-8)
并在IMG标记中使用它:
1 | <IMG SRC=jAvascript:alert(document.cookie)> |
有许多不同的UTF-8编码符号为我们提供了更多的可能性。
XSS使用代码编码
我们可以在base64中对脚本进行编码并将其放在META标记中。这样我们完全摆脱了alert()。
1 | <META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg"> |
这些和其他示例可以在XSS Filter Evasion Cheat Sheet中找到,它是备用XSS语法攻击的真正百科全书。
<
转义<
,>
转义>
,"
转义"
,空格转义
)ng-bind-html
,$sce.trustAsHtml()
ck.config.allowedContent
(HTML内容过滤,建议在设置之前阅读安全性最佳实践)HTTP响应头 | 描述 |
---|---|
X-XSS-Protection: 1; mode=block | 该响应头会开启浏览器的防 XSS 过滤器 |
X-Frame-Options: deny | 该响应头会禁止页面被加载到框架 |
X-Content-Type-Options: nosniff | 该响应头会禁用客户端的 MIME 类型嗅探行为,参考这里 |
Content-Security-Policy: default-src ‘self’ | 该响应头是防止 XSS 最有效的解决方案之一。它允许我们定义从 URLs 或内容中加载和执行对象的策略,参考这里 |
Set-Cookie: key=value; HttpOnly | Set-Cookie 响应头通过 HttpOnly 标签的设置将限制 JavaScript 访问你的 Cookie |
Content-Type: type/subtype;charset=utf-8 | 始终设置响应的内容类型和字符集 |
CSRF攻击者在用户已经登录目标网站之后,诱使用户访问一个攻击页面,利用目标网站对用户的信任,以用户身份在攻击页面对目标网站发起伪造用户操作的请求,达到攻击目的。
通常使用以下技术之一完成:
漏洞利用网址可以伪装成普通链接,鼓励受害者点击它:
1 | <a href="/rest/users/delete-all">click here</a> |
或者作为0x0假图像:
1 | <img width="0" height="0" src='/rest/users/delete-all'> |
GET和POST攻击之间的唯一区别是受害者如何执行攻击。
此类请求无法使用标准a
或img
标记进行传递,但可以使用form
进行传递:
1 | <form action="/rest/users/delete-all" method="POST"> |
此表单将要求用户单击提交按钮,但这也可以使用JavaScript自动执行:
首先在另一个网站上传以下代码:
1 | <html lang="en-US"> |
1 | <html lang="en-US"> |
当被攻击用户去访问main.html时,他浑然不知浏览器悄悄地给另一个网站发送了修改设置的请求,显然浏览器在发送请求时自觉地还带上了被攻击网站的cookie。
如果把代码中的action换成微博的API,我们就能实现:如果你的浏览器已登录了微博,那你访问这篇文章的同时,就自动关注了我的微博。
究其原因:
学到这里我突然想到一个问题,JS可以读取页面iframe元素的内容,那我是否可以实现CSRF的同时读取到服务端返回值了呢?这样岂不是可以造成数据泄露?
1 | setTimeout(function() { |
开发浏览器的人早就想到了这个问题,只要是跨域的iframe读取与操作,都是不允许的。Uncaught DOMException: Blocked a frame with origin "null" from accessing a cross-origin frame.
直接把上面代码利用XSS漏洞,嵌入被攻击站点,这组合攻击方式称为XSRF。
CSRF攻击的一般是由服务端解决。
如果网站同时存在XSS漏洞,依然可以通过JS获取到Token。
CRLF是”回车换行”(\r\n
)的简称。在HTTP协议中,HTTP Header与HTTP Body是用两个CRLF分隔的,浏览器就是根据这两个CRLF区分HTTP头和HTTP体。
所以,一旦我们能够控制HTTP头中的字符,注入一些恶意的换行,这样我们就能注入一些会话Cookie或者HTML代码,所以CRLF Injection又叫HTTP Response Splitting,简称HRS。
在以下情况下发生HTTP响应拆分:
对于HRS最简单的利用方式是注入两个\r\n,之后写入XSS代码,来构造一个XSS。
比如一个网站接受URL参数/redirect?url=
,URL放在Response Location后面跳转。
1 | GET /redirect?url=new-page |
1 | 302 |
如果我们输入的是
1 | GET /redirect?url=%0d%0a%0d%0a<img src=1 onerror=alert(/xss/)> |
1 | 302 |
糟了,由于Location为空,Chrome并没有跳转,而是把两个CRLF后的<ing>
渲染了出来,造成了XSS注入。
此攻击方式由于会注入返回头,危害大于XSS,其能够轻松修改返回头,导致浏览器XSS Auditor,Frame Deny等防护失效,还能恶意注入cookie的JSESSIONID
实现会话固定漏洞。
TODO
SQL注入攻击通过从客户端或Web到服务端的输入数据包括SQL查询的注入。成功的SQL注入攻击可以从数据库读取敏感数据,修改数据库数据(插入/更新/删除),对数据库执行管理操作(如关闭DBMS),恢复DBMS文件中存在的给定文件的内容系统并在某些情况下向操作系统发出命令。
1 | select * from users where username='test' and password=md5('test') |
封面来源: pixabay, free for commercial use.
]]>举个栗子,这里的clickOutside是从用的地方传入的一个方法,debug时我们会发现绑进来的clickOutside
并不是我们传的clickOutSideAction
。
1 | app.directive('clickOutSide', ['$document', function($document) { |
1 | <div data-click-out-side click-Outside="$ctrl.clickOutSideAction()"></div> |
如果需要在这里给clickOutSideAction传参数,应该这样改:
1 | app.directive('clickOutSide', ['$document', function($document) { |
1 | <div data-click-out-side click-Outside="$ctrl.clickOutSideAction(event)"></div> |
好处是在实际使用directive的地方,不需要考虑参数列表顺序,只需要保证参数名称正确。
]]>TODO
JUnit框架用一组assert方法封装了一些常用的断言。这些assert方法可以帮我们简化单元测试的编写。这样的话,Junit就可以根据这些断言是否抛出 AssertionFailedError 错误来判断测试用例的执行结果。
使用过Junit 的应该有过体验:在实际开发中,一些基本的断言,如eqaul,null,true它们的可读性并不是很好。而且很多时候我们要比较对象、集合、Map等数据结构。这样我们要么进行大段的字段获取再断言。或者干脆自己编写表达式并断言其结果。
JUnit4.4引入了Hamcrest框架,Hamcest提供了一套匹配符Matcher,这些匹配符更接近自然语言,可读性高,更加灵活。
Hamcrest 提供了大量被称为“匹配器”的方法。其中每个匹配器都设计用于执行特定的比较操作。Hamcrest的可扩展性很好,让你能够创建自定义的匹配器。最重要的是,JUnit也包含了Hamcrest的核心,提供了对Hamcrest的原生支持,可以直接使用Hamcrest。当然要使用功能齐备的Hamcrest,还是要引入对它的依赖。
Tutorial: http://hamcrest.org/JavaHamcrest/tutorial
API: http://hamcrest.org/JavaHamcrest/javadoc/2.1/
1 | import java.util.ArrayList; |
1 | import org.junit.Assert; |
1 | package Matchers; |
1 | package Matchers; |
harmcrest的核心类从Matchers转为CoreMatchers。用户在使用的时候需要注意更新。
当使用assertThat时,静态导入时,导入的路径变为:
1 | import static org.hamcrest.CoreMatchers.*; |
封面来源: pixabay, free for commercial use.
]]>这是篇瞎球折腾笔记。
CI是个好东西,前段时间看了一本关于DevOps的书,对持续集成有了一定了解。
Hexo博客本身拥有很简洁的编译、部署过程:
1 | hexo g |
但是简单的基础是前戏太多:
配置SSH,拉项目,拉子模块,安装NodeJS,安装脚手架,安装依赖……
虽然命令多,但是比较单一,便首先想到了给Hexo写CI脚本。
使用的第一个平台是腾讯云开发者平台(dev.tencent.com),它提供基于Jenkinsfile的持续集成beta版本
优点:免费,全中文界面,配置简单易于上手,支持Jenkins,国内服务速度快
缺点:目前功能较少,不支持上传secret files,无法配置SSH,npm依赖下载缓慢
hexo d
命令是需要调用git push
的,不支持SSH就凉了,过程就不讲了,在经过一番折腾后,我选择放弃了这个平台。
第二选择是自己搭建Jenkins,一番折腾后,发现自己的VPS性能太差,而且Windows版一些配置难以用配置文件完成,要手动配置,考虑到未来迁移起来会困难,逐放弃……
优点:完全免费,网上资料丰富
缺点:配置复杂,需要自行搭建,性能依赖于VPS性能
最后成功地在巨硬(Microsoft)Azure DevOps上配置好了,跟大家分享步骤!
优点:免费(一个月1800分钟、1个并行job),runner质量高,配置方便
缺点:Web hook不稳定,2次遇到GitHub调不通而没有自动触发Trigger的情况,与其他CI配置不兼容,参考资料较少
1 | trigger: |
国外CI runner依赖下载速度甩了腾讯几条街,1分钟一次build,免费时间一个月是用不完的。
如果你遇到了部署失败,可以访问 Azure DevOps的帮助文档 中寻找答案,也欢迎粘贴log讨论!
封面来源, Cover source: https://www.10thmagnitude.com/azure-devops-whats-in-a-rename/
]]>原理是生成一个相同样式的,隐藏的span,通过span的宽度动态改变input的宽度。
同时兼顾了input有placeholder的情况。
如果是在比较大的系统中,可以用throttle节流阀包装一下resize方法,避免性能问题。
如果是textarea,对应的directive在这里:
https://github.com/monospaced/angular-elastic
效果:
See the Pen input auto size directive by iMaeGoo (@iMaeGoo) on CodePen.
1 | <div ng-app="Test" ng-controller="MainCtrl"> |
1 | var app = angular.module('Test', []); |