Python使用logging为Flask增加logid

我们为了问题定位,常见做法是在日志中加入 logid,用于关联一个请求的上下文。这就涉及两个问题:1. logid 这个“全局”变量如何保存传递。2. 如何让打印日志的时候自动带上 logid(毕竟不能每个打日志的地方都手动传入)

logid保存与传递

传统做法就是讲 logid 保存在 threading.local 里面,一个线程里都是一样的值。在 before_app_request 就生成好,logid并放进去。

因为需要一个数字的 logid 所以简单使用 uuid.uuid1().time 一般并发完全够了,不会重复且趋势递增(看logid就能知道请求的早晚)。

打印日志自动带上logid

这个就是 Python 日志库自带的功能了,可以使用 Filter 来实现这个需求。

log_format 中我们用了很多系统自带的占位符,但 %(logid)s 默认没有的。每条日志打印输出前都会过 Filter,利用此特征我们就可以把 record.logid 赋值上,最终打印出来的时候就有 logid 了。

虽然最终实现了,但因为是通用化方案,所以有些复杂了。其实官方教程中介绍了一种更加简单的方式:injecting-request-information,看来没事还得多看看官方文档。

iTerm2进阶使用技巧

iTerm2 的优点这里不做赘述了,第一次使用的话可以先看看官网的介绍:featuresHighlights for New Users。本文主要是结合实际使用场景,介绍一些进阶使用技巧(基本的 Oh My Zsh、rzsz 等配置就不重复说明了)。

跳板机自动登录

现在很多公司登录服务器都需要先登录到一个跳板机然后再登录到目标机器,每次输入密码(一般还是动态的)很麻烦。一般的教程推荐使用 expext 解决这个问题,这里介绍一个更简单、直接的办法。

首先,要先解决登录到跳板机的连接复用问题,这个输入 ssh 本身的范畴,一般教程都是说在 ~/.ssh/config 增加下面的配置:

但这样有个问题,iTerm2 第一次登录的 tab 关闭后,就失效了,再登录就又要密码了。其实再增加一个配置即可。

之前的设置只是实现了连接复用,但 tab 关闭 ssh 进程结束后,连接也被销毁了,ControlPersist 项的意思是进程结束后连接还保持,再有相同的(ControlPath配置)连接,还能继续使用此连接。

再者,每次输入 ssh xxx 很麻烦(而且跳板机登录后还得输入 ssh xxx),当然你可以配置 alias+expext 但也不是太方便,特别是 Windows 转过来的。对此,iTerm2 本身也提供了很强大的 Profiles 功能,能一键登录目标机器(还可以设置快捷键)。

有些自己的常用机器,还可以复制一下这份基础的 relay 配置。

再加一行(Send text at start处)。

还可以把机器打个标签,然后页面上就能分组,方便选择。

还有一个,有时候会发现,有些机器一会儿没操作就会被断开 ssh,一方面可以设置 ServerAliveInterval,但作用不大,因为实际连接服务器的是 relay 跳板机。iTerm2 其实没有可以显式设置这个功能的地方,有些同学可能找到个这个配置: Continue Reading...

WordPress通用优化策略及常用插件推荐

WordPress 安装很方便,可以说是开箱即用。但是随着文章增多,访问量增大,会发现 WordPress 很“慢”。这是 WordPress 本身的 PHP 运行机制导致的,每篇文章都要去数据库读取,而且 WordPress 为了支持各种功能,现在已经非常臃肿,每次请求都要加载很多东西。但正是 WordPress 的功能强大,让我们也能很方便的做各种优化。

0x1 使用最新版本的 PHP 和 MySQL

毫无疑问升级基础运行环境是提高性能最好的方式之一。特别的 PHP7 和 MySQL 5.7 较之前的版本性能提升很大。还可以根据服务器配置适当调整 PHP-FPM 和 MySQL 参数

0x2 使用缓存

这里的缓存有两层意思,一是 PHP 层面的运行数据缓存,二是文章页面静态化。这里推荐几个插件来解决这个问题:

Redis Object Cache

一款持久对象缓存插件。其实 WordPress 本身带有对象缓存功能,但是是把序列化的对象缓存在文件中,效果不是很好。这个插件通过重写 object-cache.php 文件,把对象缓存到 Redis。直观的感受就是不光前台页面加载速度快了,而且后台响应速度提升更大。

Cache Enabler

keycdn 公司开发的一款页面静态化缓存的插件。相比 wp-supercache 等插件更加简洁和强大。建议按照官方说明进行增强设置,官方的配置有一点小问题,当你的永久链接格式设置为 xxx.html 时 $cache_uri(默认是 $request_uri)没有后面的 / 拼凑的文件路径不对(xxx.htmlindex.html),需要改成 ${cache_uri}/index.html,这样虽然访问首页时中间会多个 / 但也不影响。

我使用的是 Nginx,除了正常设置 gzip 外还开启了 gzip_static 参数,让 Nginx 在读取文件的时候优先读取带 gz 后缀的静态文件,不用再做 gzip 压缩。

顺带推荐一个 gzip 检查网站:https://www.giftofspeed.com/gzip-test/

不过使用高级设置后需要把缓存有效期设置为 0(永不失效),可能会造成缓存不会被更新(正常情况下更新文章缓存会被更新)。这里我是通过删除缓存文件然后访问自己 sitemap 中的链接来刷新缓存:

https://gist.github.com/iyaozhen/53e6a57a2f7e945ba1161953959a7cb2

Nginx open_file_cache

上一步我们已经将网站静态化,访问一般的文章页面,其实相当于打开 html 文件,但文件打开关闭也是有开销的,这个能否优化呢?答案是可以的,nginx 提供了 open_file_cache 功能,简单配置即可

此配置是让 nginx work 保持最常访问的文件句柄,不是缓存文件内容(nginx 发送文件是内核态直接发送的,不用应用层用户态保持文件内容),对于中小站点很实用,我们可以通过 sudo lsof -p pid 查看进程打开的文件句柄。这一通骚操作后,TTFB 能降到 10ms 以下。

0x3 使用 CDN 和图片压缩

用户有时候感觉网站慢,更多的是静态资源加载慢。页面上的 JS、CSS、图片等都需要消耗服务器带宽。而且中国地域辽阔,跨地区、跨运营商更是问题。这时就需要 CDN 了。现在国内各个云都在相互竞争,CDN 比较便宜,免费的也有很多。我之前使用的是七牛云,不过自从服务器迁到腾讯云之后, CDN 也换到了腾讯(免费12个月)。这里推荐同为 keycdn 出的 CDN Enabler 插件,能将页面中的链接替换为 CDN 链接。同时推荐使用 WP SmushCompress JPEG & PNG images 压缩图片(有条件的还可以付费开启 webp),还有使用 BJ Lazy Load 实现图片懒加载(显著提高首屏加载速度)。最后不要忘记站点和 CDN 都配置一下防盗链。

0x4 升级到 HTTP2

HTTP2 支持请求复用,能提高50-70%的加载速度。首先要配置 HTTPS,再简单的配置下就能支持 HTTP2 了。当然静态资源使用的 CDN 最好也要支持 HTTP2,目前国内厂商基本都支持。

0x5 配置dns-prefetchpreconnectprerender等资源加载参数

Continue Reading...

WordPress 国内优化

众说周知 WordPress 是全球使用量第一的开源博客系统,本博客就是基于此搭建的。但是 WordPress 在国内有些水土不服,有些地方没有考虑中国的国情(GFW),需要做一些小优化。以下代码直接添加在主题或者子主题的模板函数 (functions.php)文件中即可,此文件可在后台直接编辑(外观->编辑)。

1. 移除 Google CDN 字体。英文博客使用 web-font 还是很不错,各个平台使用同一种字体,极大地提升了用户体验,但是中文博客基本用不上,而且 Google CDN 被墙,还会极大影响页面加载速度,所以还是直接去掉吧。

2. Gravatar 地址替换。WordPress 默认使用的几个 Gravatar 头像地址都被墙了,建议替换为 V2ex 提供的 CDN 地址(支持 HTTP2)。注意,官方地址路径为 /avatar,V2ex 的 CDN 为 /gravatar。

3. 使用最新的 jQuery 以及使用 CDN(BootCDN,支持 HTTP2)。需要注意测试,可能有些插件会有兼容问题。

4. 移除自动 dns-prefetch。WordPress 4.6 增加了 dns-prefetch 功能,他会分析页面注入的 js 等脚本然后,加入 DNS 预加载列表。wp-includes/general-template.php:

当然这个功能出发点是好的,但是有些域名解析很慢,预加载可能会拖慢速度,而且我也不需要使用 emoji 和 Google 字体(默认预加载了这两项)。

建议使用插件 instant-articles 来手动设置 DNS 预加载。

目前本博客只进行了这几点国内环境的特色优化,若其它小伙伴还有什么黑科技欢迎交流。当然除了中国特色,也有一些很有效的通用优化策略:WordPress通用优化策略及常用插件推荐

参考资料:

最近针对 V2EX 的 Gravatar 头像加载做了一个优化,https://www.v2ex.com/t/141485

https://www.wpbeginner.com/wp-themes/replace-default-wordpress-jquery-script-with-google-library/

https://wordpress.org/support/topic/remove-the-new-dns-prefetch-code/

创建 redis systemd 服务

服务器操作系统一直使用的是 ubuntu server,因为安装软件很方便,直接apt-get install就行。但使用 apt 安装 redis 版本比较旧,也没有新的源,所有只能自己编译安装了。不过有个问题,自己编译安装的启动和重启比较麻烦(启动:/usr/bin/redis-server /etc/redis/redis.conf,停止:/usr/bin/redis-cli shutdown)。我在想能不能使用类似 ubuntu service xxx restart 的指令。

搜索了一下发现可以使用upstart来实现这个需求,但是这个在 ubuntu 15.04 已经废弃了,推荐使用更先进的systemd。在 /etc/systemd/system/ 下创建一个 redis.service:

其中主要是定义了启动用户,启动命令,停止命令。有个设置比较重要Type=forking,可以理解为 systemd 是一个类似 supervise 的守护进程,forking 表示服务管理器是系统 init 的子进程,用于管理需要后台运行的服务。同时还需要修改 redis 的配置:

然后就可以使用sudo systemctl start redis命令启动 redis 了。同时支持 stop、restart 等常用指令。启动成功后运行 sudo systemctl status redis查看运行状态:

可以看见 redis 已经正常运行了。可以尝试使用 kill -9 命令把 redis 杀死,你会发现 redis 马上又会被拉起,这样能保证服务能一直运行(当然若是服务有问题一直蹦,谁也救不了你)。若需要开机启动还可以运行sudo systemctl enable redis命令加入到开启启动项里面。

我们平常自己写的程序也可以依样画葫芦写个配置文件,使用 systemctl 来做服务管理,这种方式更加先进,还有一些其它实用的功能。

 

参考资料:

Ubuntu systemd service file for Redis, https://gist.github.com/geschke/ab6afa91b2d9dfcd5c25

systemd - ArchWiki, https://wiki.archlinux.org/title/Systemd

How To Install and Configure Redis on Ubuntu 16.04 | DigitalOcean, https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-redis-on-ubuntu-16-04

PHP单元测试-mock和数据库测试

在计算机编程中,单元测试(英语:Unit Testing)又称为模块测试, 是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。

本文主要是根据PHPUnit(The PHP Testing Framework)文档结合实例简单介绍一下 PHP 单元测试中 mock 和数据库测试。如果你是初次接触单测的话建议先看一下 PHPUnit 文档中的入门章节

通常来说是开发程序和单测是同步进行的,项目提测的时候核心模块都需要包括单测(报告),但这个要求在不同的公司、部门、项目组要求不一样。虽然单测会占用一定的开发时间但总的来说单测是利远大于弊,最大的好处是自己或者别人后续更新模块功能时不用担心对原有功能造成了影响而不知情。

下面是一个具体的例子,在 web 开发中这样一个场景可能很常见:PHP 提供一个帐号注册的接口供前端调用,接口先检验一下此用户名是否已经存在,不存在的话插入数据库,返回注册成功。接口代码是这样的:

主要调用了 Join 类的 signIn 方法。我们来看看 Join 类是啥样:

逻辑很简单,先调用 Db 类的 exists 方法判断用户名是否存在,不存在的话使用 insert 方法插入数据。Join 类是这次业务新加的,比较重要,需要单测来保障质量,但这里用到了个 Db 类,这个库是以前就有的(坑),可能会影响本模块单测的正确性,而且 Db 类需要连接数据库,比较麻烦,这种场景就需要 mock 了。本文说的 mock 是广义上的,包括 Stubs(桩件)和仿件对象(Mock Object)。

将对象替换为(可选地)返回配置好的返回值的测试替身的实践方法称为上桩(stubbing)。可以用桩件(stub)来“替换掉被测系统所依赖的实际组件,这样测试就有了对被测系统的间接输入的控制点。这使得测试能强制安排被测系统的执行路径,否则被测系统可能无法执行”。

将对象替换为能验证预期行为(例如断言某个方法必会被调用)的测试替身的实践方法称为模仿(mocking)

我们这里应用的是打桩的概念。signIn 方法有两个分支:用户名存在和不存在。所以我们需要让 Db 类的 exists 方法在输入某个(些)用户名的时候返回 true。主要使用 PHPUnit_Framework_TestCase 类提供的 getMockBuilder() 方法来建立一个桩件对象:

代码看上去很像是实例化了一个类,其实原理也和这个差不多,PHPUnit 通过反射机制获取到类及其方法的信息,然后使用内置模板生成一个新类。我们需要 mock 掉 insertexists 方法:

这里使用了桩件生成器的 setMethods() 方法来设置哪些方法被上桩,以下是生成器提供的方法列表:

  • setMethods(array $methods) 可以在仿件生成器对象上调用,来指定哪些方法将被替换为可配置的测试替身。其他方法的行为不会有所改变。如果调用 setMethods(null),那么没有方法会被替换。
  • setConstructorArgs(array $args) 可用于向原版类的构造函数(默认情况下不会被替换为伪实现)提供参数数组。
  • setMockClassName($name) 可用于指定生成的测试替身类的类名。
  • disableOriginalConstructor() 参数可用于禁用对原版类的构造方法的调用。
  • disableOriginalClone() 可用于禁用对原版类的克隆方法的调用。
  • disableAutoload()可用于在测试替身类的生成期间禁用 __autoload()

然后分别设置两个方法的参数和返回值。这里 insert 操作比较简单,可以用 willReturn($value) 返回简单值:

上面的例子中,使用了 willReturn($value) 返回简单值。这个简短的语法相当于 will($this->returnValue($value))。而在这个长点的语法中,可以使用变量,从而实现更复杂的上桩行为。我们这里的需求是需要根据预定义的参数清单来返回不同的值,显然这是一个映射(map),PHPUnit 提供现成的 returnValueMap() 方法来做这个事情:

完整的单测代码: Continue Reading...

【译】简单介绍通过Predis库在PHP中使用Redis

本文翻译自 《An Introduction to Redis in PHP using Predis》,已得到作者 @Daniel Gafitescu 的允许。原文版权归作者和 sitepoint.com 所有,如果你有原文使用需求请自行联系作者。

Redis 是一个开源的内存数据库服务器,得益于内建的数据类型,Redis 不仅仅只能做简单的 key/value 存储。

Redis 由 @Salvatore Sanfilippo 在 2009 年发布,因为其受欢迎和增长迅速,被很多大公司比如 VMware(后来聘请作者去全职工作)、GitHub、Craigslist、Disqus、Digg、Blizzard、Instagram 等(详见:https://redis.io/)使用。

你可以使用 Redis 做会话(session)处理程序,当你使用负载均衡的分布式服务时特别有用。Redis 也可以用作发布/订阅系统,很优雅的创建一个在线聊天或者实时订购程序。关于 Redis 的文档,所有的命令以及其它信息都能在项目网站 redis.io 上找到。

一直以来都有 Redis 和 Memcache 哪个更好的争论,文章 as the benchmarks show 显示在相同的基础操作上两者不相上下。Redis 比 Memcache 有更多的特性,比如内存存储、磁盘持久化、原子操作、事务以及不用记录每一次变化到磁盘上而是用服务端的数据结构来代替。

在这篇文章中将介绍如何使用 Predis 库所提供的一部分基础但很有用的 Redis 命令。

容易安装

Redis 容易安装,简明的安装说明发表在产品的下载页。从我个人经验来看,如果你运行在 Ubuntu 上而又没有安装 TCL(只需运行 sudo apt-get install tcl 即可安装)将会报错。一旦 Redis 安装完成,你可以运行服务:

Redis 的网站上显示的有很多语言可用的 Redis 客户端,每种语言都有好几个。对于 PHP 来说有 5 个。在本文中我使用的是 Predis 库,但是你可能也需要作为 PHP 模块编译、安装的 phpredis 扩展

译者注:有些人可能在 Predis 库和 phpredis 扩展中难于选择,但两者在一般场景下相差不大,目前都支持 PHP7。phpredis 扩展在性能上可能有一些优势,而 Predis 库源码更加优雅(适合学习、阅读),支持 PHP 新的语法特征,但文档较少(这也是我翻译这篇文章的主要原因)。还有,Predis 也有扩展支持(但作者好像没精力维护了,目前还不支持 PHP7),用于提高性能和提供一下其它的特性。

如果你向我一样在机器上安装的有 Git,你只需克隆 Predis 仓库。否则你就要下载 ZIP 包然后解压。(译者注:可以使用更加简便的 composer 安装:composer require predis/predis

测试一下,创建一个如下内容的 test.php 文件,测试是否能通过 Predis 连接上运行着的 Redis。

当你运行这个脚本,你应该能如愿的看见(输出)信息:"Successfully connected to Redis"。

译者注:这里可能有点小问题,代码不会按照预期捕获 Redis 连接失败的异常,因为在初始化 Redis 客户端类的时候并没有真正的连接,而是在运行第一个命令时才做连接,所以需要额外运行一下 $redis->connect(); 来触发连接操作。详见:https://github.com/predis/predis/issues/61

使用 Redis

在这个章节你将了解众多 Redis 提供的命令的概况。Memcache 也有相似的命令,如果你熟悉 Memcache,这些列表对你来说看起来都不会陌生。 Continue Reading...

Nginx HTTPS 配置实践

前言

博客使用 HTTPS 已经有一段时间了,最近把当时的配置过程梳理了一遍,希望能对有需要的同学有所帮助。

概念介绍

最近 HTTPS 是越来越流行了,前一阵子的百度,最近的淘宝、知乎,都已经开启了全站 HTTPS 的时代。HTTPS 即 Hypertext Transfer Protocol Secure,简单理解就是在 HTTP 协议上加了一层加密。具体的细节以后弄透彻了再写写。

无利不起早,那么 HTTPS 的好处是什么呢?我个人觉得有以下几点:

  1. 数据传输加密,防止信息被窃取。使用 HTTP 协议时,用户的密码、银行账户、隐私信息等都是在网络上明文传输,很容易被中间人截取。
  2. 防欺诈。当你使用 EV 级别证书(https://www.wosign.com/EVSSL/index.htm)时,浏览器网址显示和一般 SSL 证书不一样。可以对比下:https://www.paypal.com/signin/ 和 https://www.baidu.com/。使用此类证书的网址,主流的浏览器都会在地址栏显示企业的名称(支持中文),增加了网站信任度,进一步防止用户被钓鱼网站欺骗,当然证书的价格也更贵一些。
  3. 防止劫持。这点可以说是国内各大公司下决心支持 HTTPS 的主要原因了。一旦被劫持,用户访问速度会变慢,看到的内容会被篡改,比如商家在百度投放的广告被替换成竞品的广告,淘宝的商品被带上小尾巴(返利链接),甚至直接跳转到x东。这些不光是损害用户的利益,更是直接影响公司收入。
  4. 使用新的技术。比如 SPDY/HTTP2(头部压缩、连接复用、Server Push等) 的基础都是 HTTPS,新协议对移动端 APP 性能提升帮助很大:《双11手淘前端技术: H5性能最佳实践》

当然 HTTPS 不是银弹,不是用了就保险了,安全是一个整体,这是典型的水桶场景,往往一个系统被攻破是在其薄弱的环节。

证书申请

证书申请的大概流程是,首先在自己的服务器使用 openssl 命令(尽量使用高版本的 OpenSSL,除了能规避漏洞,还能使用更高级的密钥加密/交换算法,提升安全性和性能)生成 csr 和 key 文件,命令如下:

如命令参数所示,私钥 key RSA 的加密强度是 2048 位(rsa:2048)。CSR 文件使用了更安全的 sha256(SHA-2)摘要算法(SHA-1算法在2016年将不被证书厂商和现代浏览器支持)。

-subj 参数指定证书申请者的信息,如果不直接使用此参数,也会有交互式的命令提示填写这些参数。此部分具体参数释义:

Country Name (2 letter code): 输入国家地区代码,例如中国的 CN

State or Province Name (full name): 地区省份

Locality Name (eg, city): 城市名称

Organization Name (eg, company): 公司名称

Organizational Unit Name (eg, section): 部门名称

Common Name (e.g. server FQDN or YOUR name): 申请证书域名,如果是泛域名证书,则应该填写 *.example.com

Email Address: 电子邮箱

命令还会提示输入challenge password,这个不是加密证书,而是相当于一个二次认证密码,如果厂商证书支持challenge password,而且你也设置了的话,后续证书操作需要验证这个密码,提高安全性。

生成的 CSR(Certificate Signing Request,即证书签名请求,不是证书)文件包含了证书的主要信息和公钥,同时生成了私钥 key 文件(注意保存)。然后把 CSR 文件提交给 CA 厂商(不用提交 key 文件),一般提交的时候会让你选择服务器类型,本文指选的 Nginx。中间还会有一个域名所有者验证过程,一般几分钟后(根据证书类型不同,时间不一样)就会发一份邮件给你。

邮件附件一般会带有厂商用 CA 私钥签好的证书文件 example.com.cert.pem(包含 域名、CA 信息,key 对应的公钥,CA 的签名)。同时会给你 CA 的证书链 example.com.cert.ca.pem,如果 CA 证书是多个文件(通常包括 1-2 个中间证书和 1 个根证书),那么需要按照证书信任链由下游到上游,把文件合并成 example.com.cert.ca.pem(cat COMODOECCDomainValidationSecureServerCA.crt COMODOECCAddTrustCA.crt AddTrustExternalCARoot.crt > example.com.cert.ca.pem)。不用把根证书放进 CA 证书链文件里面,因为浏览器和操作系统都内置了根证书,也只认自己内置的根证书。

不过现在更流行的是使用 acme.sh 自动申请和续签 Let’s Encrypt 证书,即免费又好用。acme.sh 提供的方式有很多种,大家按需配置即可,我是 DNSPod + Nginx,仅供参考:

证书处理

后面的步骤各个 HTTP Server 就有点不一样了:

tomcat 则比较特别,证书编码格式需要的不是 pem 而是 JKS,得转换一下。

到这里为止出现了好几个文件,可能有点迷糊,这里总结一下

文件名
释义
example.com.csr
Certificate Signing Request,证书签名请求,不是证书
example.com.key.pem
证书私钥(key),不能泄露(即使是对 CA 厂商),和CSR文件成对存在
example.com.cert.pem
自己的域名证书(pem格式),包含 key 对应的公钥
example.com.cert.ca.pem
CA厂商证书链(pem格式)
example.com.cert.full.pem
合并了自己证书和CA证书的完整证书链(pem格式)
example.com.key.cert.pem
合并了key和域名证书的文件(pem格式)
example.com.cert.pfx
pfx/p12格式的完整证书链(包含了key)
example.com.cert.jks
jks格式(JAVA)的完整证书链(包含了key)

对于这几种文件的区别,可以参考:https://www.cnblogs.com/yjmyzz/p/openssl-tutorial.htmlhttps://blog.freessl.cn/ssl-cert-format-introduce/。实际不用那么麻烦,一般证书厂商会提供不同 webserver 的配置文件,如果没有则需要动手一下,或者使用证书厂商提供的转换工具

TLS握手简述

借由这几个证书文件,简单介绍一下 TLS 的握手过程(RSA 密钥交换方式):

客户端
服务端
ClientHello
明文发送握手请求(上报支持的能力)
生成一个随机数r1
ServerHello
明文返回域名证书(example.com.cert.full.pem)
还会返回一个随机数r2
这里服务端也可以要求客户端提供证书进行校验(流程会有所不同,省略)
对证书进行验证,前面有介绍,证书中包含 CA 信息和签名信息,逐级向上验证即可
ClientKeyExchange
验证通过后从域名证书中拿出公钥,然后使用公钥加密PreMasterSecret(随机生成),发送给服务端(密文)
服务端使用私钥(example.com.key.pem)解密得出PreMasterSecret
客户端使用r1、r2、PreMasterSecret生成session key(会话密钥)
服务端也用同样的方式生成session key,生成算法相同(PRF
使用session key进行对称加密

可以看出核心就是 PreMasterSecret 是密文,其它都是明文。如果中间人想要截取就只能替换证书中的公钥(用自己私钥解密),因为证书本身也有完整性签名,就只能替换整个证书,但证书又是一级级到 Root CA 校验,所以 TLS 握手的结果是安全的。

证书逐级验证的过程(来源:https://security.stackexchange.com/questions/56389/ssl-certificate-framework-101-how-does-the-browser-actually-verify-the-validity

才疏学浅,介绍的非常简陋,建议阅读 https://halfrost.com/https_tls1-2_handshake/ 及系列文章

配置详解

下面正式开始 Nginx 的配置详解。 Continue Reading...

巧用七牛CDN的镜像功能使百度分享支持HTTPS

update 2020-01

百度分享已经彻底凉了,这类工具也没人愿意做,其实也很简单,自己弄一个就行。

各种社交网站的分享接口可以参考:https://github.com/overtrue/share.js,其实国内也就新浪微博和微信值得分享。

其中微信特殊一点,桌面端浏览器访问需要生成一个二维码,让用户扫码分享,对于移动端如果支持navigator.share则可以调起系统分享菜单(https://web.dev/articles/web-share),对于不支持的浏览器提示通过右上角或者底部分享。

---分割线---

唉,好懒呀,好久没更新博客了。

最近搞了个 HTTPS 证书,像以前一样给博客添加了个百度分享(http://share.baidu.com/)的组件,但发现百度分享不支持 HTTPS(百度分享图标出不来,console 会提示页面有不安全的脚本元素)。看了其它几家也都不支持,搜索了下发现有人建议把百度分享所需的 js 都保存到自己本地就行了。这也是个办法,分享功能大多是抓取这个页面的 title、摘要、图片等然后起调一个页面完成分享,这些都是本地 js 文件能完成的。

看了下从百度分享获取的代码,里面主要加载了这个:http://bdimg.share.baidu.com/static/api/js/share.js,访问了一下果然还是不支持 HTTPS。然后我就天真的把 share.js 上传到了七牛 CDN(七牛是支持 HTTPS的,在空间设置-域名配置里面设置下就行),然而百度分享的图标还是没出来。看了下控制台,卧槽,又加载了一堆 js,作为一个全栈工程师,我非常灵性的瞅了眼代码里面有一段:domain:{staticUrl:"http://bdimg.share.baidu.com/"},原来是模块化加载,把链接替换成七牛 CDN  的链接后有些请求 404 了,我又天真的以为把这几个 js 文件补全就行,但是补完几个,又有几个文件 404 了,我可没耐心一个个文件补齐呀。

作为一个灵性码农,我马上想到七牛不是有个镜像存储功能嘛,设置一发:

20150817003746

故事就这么结束了吗?怎么可能。百度“幺蛾子”还是比较多。百度分享不光是分享功能,还有分享的数据分析。数据哪里来呢?前端埋点统计的呀,原理简单说就是监控分享时的点击事件,发送数据到后台。这其中的核心就是 http://nsclick.baidu.com/v.gif,需要统计的参数和值都以 GET 参数的形式附在链接后面。然后后端再清洗请求日志或者获取请求的时候就直接把数据入库了。但这个统计小图片也不支持 HTTPS。没办法,只能去掉了,方法也很简单,static/api/js/trans/logger.js 文件为空就行(上传个空文件、占个位)。到此才算大功告成。

上面是授之以渔,不想自己弄的,可以直接抓鱼,当然希望你也能明白其中的风险,文件是我这边的(可能有后门,当然我没有),而且哪天我流量没了可能会把文件删了。

update:2016-05-24,七牛账单已经超支,上面的代码地址已经失效,还请见谅。其实了解原理之后自己设置一个即可,或者自己 Nginx 反代一下。

一点后话:一直感觉百度分享没人维护了,在群里打听了下。应该是有人(部门)维护着(至于不支持 HTTPS 那是百度 CDN 的锅),但是现在不流行打社交牌了,公司也不重视这块了,还是 200 亿糯米 O2O 更实在,而且百度首页貌似也不显示搜索结果页面的分享次数了。

 

使用七牛云存储加速你的博客

CDN的全称是Content Delivery Network,即内容分发网络。对于它的好处我想大家都知道,但一直以来都只有大公司才用得起。但如今已经有了一些面对中小企业的CDN服务,甚至是免费的。如百度旗下的加速乐(https://su.baidu.com/),安全宝(http://www.anquanbao.com/),而且安全宝还和DNSPod进行了无缝对接,很有吸引力。还有阿里云(https://www.aliyun.com/)开放存储服务 OSS、内容分发网络 CDN。这些都不错,对于个人站长来说质量和价格都能接受。但这些都有一些限制,有些需要备案,有些对个人开发者不是十分友好。

其实对于个人站点来说,只要能加速网站上的静态文件,比如图片、js文件、css文件,网站的访问速度就会大大的提升。像我的网站空间租用的是香港的服务器,ping值基本在45左右,南北互联延迟不是问题,瓶颈在于网页的加载速度(香港的空间一直都是小水管,带宽小)。基于这个需求,七牛云存储(https://www.qiniu.com/)是个不错的选择。每个月有免费的配额,操作又比较简单。它的直接竞争对手又拍云(https://www.upyun.com/)也是个不错的选择。两者都是提供云存储、云处理、云分发的服务。由于七牛云存储后台操作简捷、直接,每个月又有免费的配额,所以个人推荐使用七牛云存储。

说了那么多现在直接进入主题,仅需三部轻松提升博客访问速度。

第一步:注册七牛云

第二步:七牛云后台设置

首先需要建立一个Bucket(空间)。使用镜像加速需要设置为公开空间。

创建一个公开空间

然后空间需要绑定一个七牛云提供的二级域名(可自由设置),如果你的域名已经备案可以使用自己的域名,不过需要一段时间审核才能生效。

绑定域名

最后开启镜像存储功能。

开启镜像加速

这里有几点需要注意: Continue Reading...

本 Blog 不支持评论,如有疑问或建议请联系我,以完善内容,期望帮助到更多的同学