0%

这一切就是从那天我收到一张 ID 卡开始的,那天我回到家,喂完家里的猫尼克就躺在沙发上玩手机,我不记得我刷了多少条推的时候,收到一条快递柜的短信。

我以为是从京东上买的东西到了,完全没有意识到这条信息的重要性,我应该早就发现有什么不一样的地方,因为接着我又收到了一条验证码,“welcome to binary empire [453287]”,可惜看上去就是一条游戏广告。

这是尼克不知道从哪个方面跳过来,慌乱中我把垃圾给打翻了,于是我只好打扫一下顺便下楼把快递取了。

快递柜位置异常的小,似乎是一封文件,果不其然,标准的 ESM 包装,里面似乎什么都没有,撕开一看只有一张卡和一个读卡器,上面有我的英文名 Hao Chan, 真是寄给我的东西?

我仔细的看了看,就是张普通的芯片卡,读卡器刚好可以插入一张卡,另一头是 USB,卡上有一个网站,应该就是通过这个网站来读取卡密钥, 有点U盾的意思。

我打开了那个网站,首先提示先插入U盾,弹出来一个对话框,要我输入验证码,我翻开短信,敲入6个字符,啪,“验证已通过”。

这不会是什么骗局吧,我突然有点懊恼自己输验证码输的太快了,或者说我的好奇心实在太强烈了。不知道明天我会不会就收到催债的短信,不管了先看着吧。

网页出现一个门一样的东西,点击进去就出来一道题,这不是汉诺塔吗?我流利地三行递归搞定,等着测试集进度条滚完,出来一句话,「道生一,一生二,二生三,三生万物」。

这又是什么刷题的网站吧,我想,还挺有意思的。

接着跳转到另外一个网站,binary empire,我终于见到了这个网站的真面目。

一片空白。

从刚才那道题我猜想这又是一个考验,我习惯性的按快捷键打开开发者模式,最底下有一串字母和数字组成的字符串,base64

https 的安全性不言而喻,有些搜索引擎甚至会对有没 https 的网站降权。

使用 https 证书的首要条件是要有 SSL 证书,在某些人(比如我)的印象里 SSL 证书动辄几百美元并且有着严格的审查,所以搞起来麻烦。但实际上现在已经有了面向个人的免费 SSL 证书了,当然你前提是你有个人域名(这个还是要花钱的~)。

对于个人,申请免费的域名型(DV)就够了,企业型(OV)和 增强型(EV)不仅昂贵而且需要人工审核。

域名型证书只要有域名的所有权就可以申请,这里以 Let’s Encrypt 为例介绍下申请流程。

Let’s Encrypt 申请过程完全自动化,并且被各大浏览器支持,由 Linux 基金会托管,安全和可靠性值得信赖。

不知道为什么在官网下载的工具在验证的时候总是会出错,这里还是以 github 上最新的版本进行操作,系统为 Ubuntu 16.04 。

首先执行以下命令下载工具:

screen

git clone https://github.com/certbot/certbot
cd certbot 

申请过程中需要更改 DNS 记录比较耗时,为了不自动断开连接,推荐使用 screen 命令

申请命令:(g.com 为你的域名,*.g.com 是你的所有子域名,它们共用一个证书)

sudo ./certbot-auto certonly --manual -d *.g.com -d g.com --agree-tos --manual-public-ip-logging-ok --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory

之后出现一长串的无规则的字母序列类似于

J_fUsCNSs_5MzaFWpbXcy71IdcH7eQgg

你需要到域名解析商那里给自己的域名添加 txt 解析(不会影响正常解析,相当于给你的某个子域名添加了“注释”,用来验证你对网站的所有权),以 dns.la 为例:

image-20180526115633874

注意主机记录那里是 _acme-challenge 而不是 _acme-challenge.g.com

注意添加之后要等几分钟或以上再按 Enter 键,因为 DNS 缓存需要时间,如果等不及的话可以用命令查看是否生效:

nslookup -q=txt _acme-challenge.g.com

然后,接着我们要做的是……

按下 Enter 后,重复再来一次!

注意第二次更不要急,因为网络上可能有上次你设置的 TXT 记录的缓存,所以你这次设置的没那么快被更新,等个十来分钟吧……

再次按下 Enter 键,如果成功的话会提示密钥存放的位置(不要急着关掉),如果没成功所有流程再来一遍……(所以不要急)

一般位置是在:

/etc/letsencrypt/live/g.com/

如果你刚才没注意看的话~~~

最后更新 Nginx 设置然后重启 Nginx (sudo service nginx restart),nginx 配置如下(把g.com 换成你的域名就好了):

server {
    listen 80;  
    server_name g.com www.g.com;
    return 301 https://www.g.com$request_uri; # 从 http 过来的跳到 https 上
}

server
{
    listen 443;   # https 端口 
    server_name
           g.com
           www.g.com;
    index index.html index.htm;
    root  /home/ubuntu/;
    error_page 404 = /404.html;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/g.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/g.com/privkey.pem;

    access_log /var/log/nginx/g.com_access.log;
}

以后再上网站就是有安全认证的~

image-20180526121410444

注意证书有效期三个月,可以在 crontab 增加如下命令每天更新(证书没过期不会执行成功,需要sudo):

43 6 * * * certbot-auto renew --post-hook "systemctl reload nginx"

最近看了些程序员方面自我提升的文章,发现自己的键盘指法不太标准,特别是在输入符号的时候经常有低头看键盘的习惯,找了些这方面的软件,无奈很多在mac上用不了,唯一一个还可以的typing.io编程练习要收费,免费版只有一些输入错误的统计,没有告诉你具体要按那个键用哪个手指。

作为一个程序员,最后用了更geek的gtypist,哈哈,用brew isntall gtypist 就可以安装了。

先敲了十几分钟,感觉还不错,每个课程前面有长长的英文指导,建议看看,然后按照指示敲就可以了。

有一点就是如果你敲错了是没办法回退的,只能硬着头皮敲下去,最后会统计错误率,如果大于3%就要再来一次。

教程完全是初步的,一行行来分解练习,适合什么基础都没有的,其实有基础的却养成了坏习惯的纠正可能会更难,笑。

记住一点,宁可敲错宁可敲慢,也不要反复看键盘,实在不行在脑海里回想一下。

细水长流,先每天就敲十来分钟,看看一个月后的效果。

  • update 2018-03-07
    断断续续用了几个星期,无聊的时候敲敲蛮有意思的,现在在mac的键盘上敲得很顺畅了,不过换个键盘还是要适应一下,这个问题似乎无解,毕竟键位一样尺寸也不一样。

最近在看Facebook的基于C++11写的一个常用工具库folly,包括内存分配、原子锁等等。

源码里有一些常用的宏定义,大致归纳一下,方便阅读(大部分来自gcc.gnu.org)。

Variadic Macros(c99特性)

可以这样定义一个可变长参数函数:

#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#define eprintf(format, ...) fprintf(stderr, format, __VA_ARGS__)

也可以这样(c++写法,如果需要考虑兼容性,c++中只应该使用该写法,c99只使用**__VA_ARGS__**):

#define eprintf(args...) fprintf(stderr, args)

但注意这种写法就不能在后面增加**__VA_ARGS__**了。

假如你的参数可能为空,可以这样写:

#define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__)

这样当**__VA_ARGS__为空时,__VA_ARGS__**前的『,』会被删除,例如:

eprintf ("success!\n")
        ==> fprintf(stderr, "success!\n");

使用Variadic Macros还有一些细节上的问题,见Variadic Macros末尾几段。

Stringification

# 定义

(hash mark)表示将随后的参数转化为字符串字面量,一般用在输出中:

#define xstr(s) str(s)
#define str(s) #s
#define foo 4
str (foo)
     ==> "foo"
xstr (foo)
     ==> xstr (4)
     ==> str (4)
     ==> "4"

xstr定义用于得到参数的值。

## 定义

用于连接字符串字面量(最好前后加空格),可以这样用:

#define COMMAND(NAME)  { #NAME, NAME ## _command }

struct command commands[] =
{
  COMMAND (quit),
  COMMAND (help),
  ...
};

等价于:

struct command
   {
     char *name;
     void (*function) (void);
   };
   
   struct command commands[] =
   {
     { "quit", quit_command },
     { "help", help_command },
     ...
   };

0

大学的时候断断续续学过一点C++的东西,记得那时用的是《accelerated c++》,对于初学者相当友好又不至于太简单只能写toy代码,后来因为搞科研开始写python代码,最近一段时间因为学习Linux方面的东西又开始看C++方面的书。其中《c++ primer 5e》和《深入探索c++对象模型》对我理解C++帮助很大,从C++和python的异同中又学到不少东西(有点像之前看《SICP》学LISP的感觉),语言确实可以改变程序员的思考方式。下面断断续续地总结一些体会和知识。

1

最初并不是很理解Python的新式类(继承object),后来代码写得多了发现新式类多了许多特性,最突出的就是type时能够返回正确的类类型。对于C++这样的语言,假如class不需要兼容struct的内存结构完全可以单根继承object,这样一个object指针就可以指向所有类型了。用void 也没问题,但void*在没转换前几乎什么都做不了,像类型这样的信息完全可以放在父类object内。当然这样会略微增加一点类实例的大小。

2

sizeof一个空的class得到的结果是1(有些编译器是零),因为需要有一个地址来做『占位符』(以便指针指向),这也说明C++在class优化真的挺彻底的,class在正确使用下并不会比struct带来更多的『负担』。

3

多线程下,即使构造函数的最后一行也不要泄露this, 因为Foo可能是基类,基类先于派生类构造,执行完Foo::Foo()后还会执行派生类的构造函数,仍然不安全。因为其他线程可能会引用到一个不完全对象。

4

异常的出现有一部分是为了处理C++中构造函数没有返回值的情况,但在析构中一般不抛出异常,因为一般的异常有可能会调用析构函数,这时又抛出异常会使得资源无法正常释放,另外异常点之后的代码不能正常执行,正常的析构无法完成的话也会有内存泄露问题。