<![CDATA[Mr.Tang]]> 2018-08-14T19:21:39+08:00 http://antientbook.com/ Octopress <![CDATA[javascript book chapter 4-5]]> 2018-05-17T19:37:27+08:00 http://antientbook.com/blog/javascript-book-4-5 javascript 高级程序设计 读书笔记

章节 4-5

4 .作用域和内存问题

5 .引用类型

1 .作用域和内存问题

只能给引用类型值动态的添加属性:

1
2
3
4
5
6
7
8
// 例子
var person = new Object();
person.name = 'Nicholas';
alert(person.name) //"Nicholas"

var name = "Nicholas";
name.age = 27;
alert(name.age); //undefined

复值变量值

1
2
3
var obj1 = new Object();
var obj2 = obj1;

]]>
<![CDATA[javascript book chapter 1-3]]> 2018-05-03T19:37:27+08:00 http://antientbook.com/blog/javascript-book-1-3 javascript 高级程序设计 读书笔记

章节 1-3

1 .JavaScript简介

2 .在html中使用JavaScript

3 .基本概念

1 .javascript 简介

一个完整的JavaScript包含:

ECMAScript

DOM

BOM

dom 文档对象模型

dom把每个页面映射成一个多层级的节点

1
2
3
4
5
6
7
8
9
10
11
12
13
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>

</body>
</html>

BOM 浏览器对象模型

BOM 只处理浏览器窗口和框架

BOM扩展:

弹出新窗口功能

移动缩放和关闭浏览器窗口的功能

提供浏览器详细信息的navigator对象

提供浏览器所加载页面的详细信息的location对象

提供用户显示器分辨率详细信息的screen对象

对cookies的支持

像XMLHttpRequest 和IE的ActiveXObject这样的自定义对象

总结:

ECMAScript,由 ECMA-262dinyi ,提供核心语言功能

DOM 文档对象模型,提供访问和操作页面内容的方法和接口

BOM 浏览器对象模型,提供与浏览器交互的方法和接口

2.在html中使用JavaScript

defer defer可以延迟加载脚本,不过与将script标标签放入body结尾处相比,更多的会使用后者,因为defer只有少数浏览器支持。

noscript 可以指定在不支持脚本的浏览器显示的替代内容。

3 .基本概念

规范,驼峰命名

关键字

break 跳出循环

else 否则

new 新建一个对象

var 定义变量

case 当 switch 变量等于case 执行代码

finally try和catch之后最终执行的代码

return 返回 之后的代码不要执行了

void 无返回值

catch 捕获异常

for 循环

switch 多个case

while 循环

continue 继续下一个循环 当前循环下的代码不执行

function 声明方法

this 当前方法被调用的对象

with

default 默认执行

if 如果

throw 抛出异常

delete 删除

in 循环对象

try 与 catch对应

do 做一次

instanceof 检查类型

typeof 检查对象type

变量 在没有使用var 声明的时候 为全局变量

var 为局部变量

JavaScript是弱类型语言

typeof

‘undefined’ 如果这个值未定义

‘boolean’ 如果这个值是布尔值

‘string’ 如果这个值是字符串

‘number’ 如果这个值是数值

‘object’ 如果这个值是对象或者null

‘function’ 如果这个值是函数

声明变量未初始化 这个变量的值就是 ‘undefined’

在保存对象的变量还没有真正的保存对象,就应该明确的让该变量保存null 值,这样做不仅可以体现出null作为空对象指针的惯例,而且有助于进一步区分null和undefined

BOOLEAN中为FALSE的值

false

空字符串

0 和 NAN

null

undefined

NAN与任何值都不相等 包括NAN本身

1
NAN == NAN  // false

Number()

true和false返回1和0

数值直接返回

null 返回 0

undefined 返回NAN

Object类型

Object的每个实例都具有以下属性和方法:

constructor 保存着用于创建当前对象的函数。

hasOwnProperty(propertyName) 用于检查给定的属性在当前对象实例中是否存在

isPrototypeOf(Object) 用于检查传入的对象是否是另一个对象的原型

propertyIsEnumerable(propertyName) 用于检查给定的属性是否能够使用for-n语句

toString() 返回对象的字符串表示

valueOf() 返回对象的字符串,数值,或布尔值表示

操作符

递增和递减的操作是在包含他们的语句求值之后才执行的

可以向函数传递任意数量的参数,可以通过arguments对象来访问这些参数

由于不存在函数签名的特性,函数不能重载

变量在声明它们的脚本或函数中都是有定义的,变量声明语句会被提前到脚本或函数的顶部。但是,变量初始化的操作还是在原来var语句的位置执行,在声明语句之前变量的值是undefined

]]>
<![CDATA[facebook api login share and instagram login]]> 2018-04-23T19:37:27+08:00 http://antientbook.com/blog/facebook-api 本篇文章主要介绍三方登录 facebook instagram

分为四个部分

1 .facebook api login

2 .facebook user info

3 .instagram api login

facebook api login

首先注册成为开发者然后注册自己的APP 选择网站website https://developers.facebook.com

url redirecturl 都设置为web app的域名

关于隐私链接 隐私链接

然后把代码放入页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<fb:login-button
        scope="publish_actions"
        onlogin="checkLoginState();">
</fb:login-button>
<script>
window.fbAsyncInit = function () {
    FB.init({
        appId: '386610931818049', // appId
        cookie: true,
        xfbml: true,
        version: 'v2.12'    // api version
    });

    FB.AppEvents.logPageView();

};
// load facebook sdk
(function (d, s, id) {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) {
        return;
    }
    js = d.createElement(s);
    js.id = id;
    js.src = "https://connect.facebook.net/en_US/sdk.js";
    fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));

// login callback
function checkLoginState() {
    FB.getLoginStatus(function (response) {
        statusChangeCallback(response);
    });
}

// callback
function statusChangeCallback(response) {
    // get user picture through api
    FB.api(
        '/' + response.authResponse.userID + '/picture',
        'GET',
        {'redirect': '0'},
        function (response) {
            // Insert your code here
            console.log(response);
        }
    );
    console.log(JSON.stringify(response))
}
</script>

登录成功后返回的用户信息为

1
2
3
4
5
6
7
8
9
{
"authResponse":{
"accessToken":"EAAFfnt9B3kEBAMsIzz4PZBYpDivuopRYzrOGew8oMZC55PaDJZByHEid2Cpm9aUf5R6qroHZCsJ3Aa7ENC44I8LZC2gjcOC6wnovGWjDhXZAkAatXKZCVkeUHFINUc5qZAv3pRN7ZAlnor8SNVtmZBqWWcnYuEMZCIC87EC0Ov4SisDGDvbgQ2kHCdtDlZBUZC1CX5uBFC7WnZBMDAhJDZA00nhEA0g",
"userID":"110712723123784",
"expiresIn":5101,
"signedRequest":"TOEoGHJcXPZTQgqVeaynfYJRGi0EnCbXl2uxILk7_mE.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImNvZGUiOiJBUUJjUVkxQWZRV2lJeHc5SHdYOW5SYXN0Y2xVX3RTVE1rQlVRU0hvTXBFbTVVaWRyYWdwcTdReXhCMTh0djhlTC0yeTQ2UjNDS3ZQV1lrV1dSTldUVzVNRmlWNlZ5X0pObVhZeVBmMDd1MlEyVzRnSHZBejhWdDkyMEN0NHFOVWg5YTJNNDh5cmItb09IU3c0VmxiWUJyZ1RGamFISlVKUVF3Um9KRlYzZVZkdXF1anpuNkM4WnpDOGRUZTJjVXc1NllBSzhzQjNqY21JTkNNUFllWGVwV1lPR0xQYVdZYWtQSW9nS2NEVS1teFNrOV9RZmU2cGJoRGZCbkNvQVVfa0E1QmY0MnBKT1g5RFBaUzBBU3doZU9UaTdsVGNycUZFRkt6c3F6VTVkQTFmOVk1c211NHFQdU50S3lFaEtsMzV5eUMyV0NvMTRrTnhWNEZCTFBYQVFwdCIsImlzc3VlZF9hdCI6MTUyNDQ1ODA5OSwidXNlcl9pZCI6IjExMDcxMjcyMzEyMzc4NCJ9"
},
"status":"connected"
}

自定义按钮 如果應用程式想要使用自己的按鈕,只需呼叫 FB.login(),即可叫用「登入」對話方塊:

1
2
3
4
FB.login(function(response){
  // Handle the response object, like in statusChangeCallback() in our demo
  // code.
});

根据accessToken 和 userID可以获取更详细的用户信息

1
https://graph.facebook.com/v2.12/110712723123784/picture?access_token=EAAFfnt9B3kEBAOb7ZCYuO3f4LSeQ3nZCkKKiV1za55ZBFSxhemumm35u0cAK9ZBNXb2bhe4venF5t8UcpjyKaD7xjeMas56QZAsxVL1ySb2JA9e5u81kHYtrTHZCU8EqMdLRPcrs4duVK8ie0B0ZCBTe9zg8b1Ba4GtyX9f0ZC83OdRqEjXsiLQi2ehaZCeFTXDYrK0ILnbZB7aZB2EYCZAkZAB9X&method=get&pretty=0&redirect=0&sdk=joey&suppress_http_code=1

返回信息

1
{"data":{"height":50,"is_silhouette":false,"url":"https:\/\/lookaside.facebook.com\/platform\/profilepic\/?asid=110712723123784&height=50&width=50&ext=1524731636&hash=AeQjW1S7SKvTa3Sy","width":50}}

这里有一个问题 返回的图片链接打开直接就被下载了

解决办法参考这个 issue https://github.com/bumptech/glide/issues/2986

Instagram api login

也是需要有自己的client 获取到clientID和clientSecret https://www.instagram.com/developer/authentication/

请求这个链接 https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code

把clientID redirect_uri改为自己的

就会得到http://redirect_uri?code=xxx

然后 用服务端发送请求获取用户信息

1
2
3
4
5
6
curl -F 'client_id=CLIENT_ID' \
    -F 'client_secret=CLIENT_SECRET' \
    -F 'grant_type=authorization_code' \
    -F 'redirect_uri=AUTHORIZATION_REDIRECT_URI' \
    -F 'code=CODE' \
    https://api.instagram.com/oauth/access_token

-F 表示FORM DATA

然后得到返回信息

1
{"access_token": "7574672867.29ceb57.e7ee82776c934c7492ecc0a73a08dd49", "user": {"id": "7574672867", "username": "tangxuelong", "profile_picture": "https://scontent.cdninstagram.com/vp/f17e1275a70fc32e93cbf434ddc32bcd/5B6CCC7A/t51.2885-19/11906329_960233084022564_1448528159_a.jpg", "full_name": "\u5510\u96ea\u9f99", "bio": "", "website": "", "is_business": false}}

Google api login

参考链接 https://developers.google.com/identity/sign-in/web/sign-in

google share

https://developers.google.com/+/web/share/

]]>
<![CDATA[nginx和PHP7.0 以ROOT身份启动 PDO_MYSQL mbstring]]> 2018-04-04T19:37:27+08:00 http://antientbook.com/blog/linux-php 本篇文章主要介绍重点实用解决问题的部分

分为四个部分

1 .安装php7.0配置nginx

2 .如何以root身份启动php-fpm

3 .安装扩展 pdo_mysql mbstring

安装php7.0配置nginx

首先安装php7.0

1
apt-get install php7.0-fpm

然后修改ngixn配置

1
2
3
4
5
6
7
location ~ \.php$ {
  include snippets/fastcgi-php.conf;
  # With php7.0-cgi alone:
  #fastcgi_pass 127.0.0.1:9000;
  # With php7.0-fpm:
  fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
}

重启nginx就可以了。

如何以root身份启动php-fpm

1)编辑/etc/php/7.0/fpm/pool.d/www.conf,把user和group修改为root

1
2
user = root
group = root

2)编辑/lib/systemd/system/php7.0-fpm.service,在ExecStart的 –nodaemonize前面加上 –allow-to-run-as-root,就像下面这样:

1
ExecStart=/usr/sbin/php-fpm7.0 --allow-to-run-as-root --nodaemonize...

3)重载配置:

1
systemctl daemon-reload

4)重启php-fpm:

1
service php7.0-fpm restart

5) 查看

1
ps auwx | grep php

就可以看到 php-fpm已经以root身份运行了

安装扩展 pdo_mysql mbstring

1
2
apt install php7.0-mysql
apt-get install php7.0-mbstring

然后修改php.ini 我的目录在/etc/php/7.0/fpm

找到

1
2
3
;extension=php_mbstring.dll
// 俩个位置不在一起 单独查找
;extension=php_mysqli.dll

把前面的分号;代表注释 给删除 然后重启php-fpm 就可以了

]]>
<![CDATA[Let's Encrypt,免费好用的 HTTPS 证书]]> 2018-04-04T19:37:27+08:00 http://antientbook.com/blog/free-https 很早之前我就在关注 Let’s Encrypt 这个免费、自动化、开放的证书签发服务。它由 ISRG(Internet Security Research Group,互联网安全研究小组)提供服务,而 ISRG 是来自于美国加利福尼亚州的一个公益组织。Let’s Encrypt 得到了 Mozilla、Cisco、Akamai、Electronic Frontier Foundation 和 Chrome 等众多公司和机构的支持,发展十分迅猛。

申请 Let’s Encrypt 证书不但免费,还非常简单,虽然每次只有 90 天的有效期,但可以通过脚本定期更新,配好之后一劳永逸。经过一段时间的观望,我也正式启用 Let’s Encrypt 证书了,本文记录本站申请过程和遇到的问题。

我没有使用 Let’s Encrypt 官网提供的工具来申请证书,而是用了 acme-tiny 这个更为小巧的开源工具。以下内容基本按照 acme-tiny 的说明文档写的,省略了一些我不需要的步骤。

ACME 全称是 Automated Certificate Management Environment,直译过来是自动化证书管理环境的意思,Let’s Encrypt 的证书签发过程使用的就是 ACME 协议。有关 ACME 协议的更多资料可以在这个仓库找到。

创建帐号

首先创建一个目录,例如 ssl,用来存放各种临时文件和最后的证书文件。进入这个目录,创建一个 RSA 私钥用于 Let’s Encrypt 识别你的身份:

1
openssl genrsa 4096 > account.key

创建 CSR 文件

接着就可以生成 CSR(Certificate Signing Request,证书签名请求)文件了。在这之前,还需要创建域名私钥(一定不要使用上面的账户私钥),根据证书不同类型,域名私钥也可以选择 RSA 和 ECC 两种不同类型。以下两种方式请根据实际情况二选一。

1)创建 RSA 私钥(兼容性好):

1
openssl genrsa 4096 > domain.key

2)创建 ECC 私钥(部分老旧操作系统、浏览器不支持。优点是证书体积小):

1
2
3
4
5
#secp256r1
openssl ecparam -genkey -name secp256r1 | openssl ec -out domain.key

#secp384r1
openssl ecparam -genkey -name secp384r1 | openssl ec -out domain.key

有关 ECC 证书的更多介绍,请点击这里

有了私钥文件,就可以生成 CSR 文件了。在 CSR 中推荐至少把域名带 www 和不带 www 的两种情况都加进去,其它子域可以根据需要添加(目前一张证书最多可以包含 100 个域名):

1
openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:yoursite.com,DNS:www.yoursite.com")) > domain.csr

执行这一步时,如果提示找不到 /etc/ssl/openssl.cnf 文件,请看看 /usr/local/openssl/ssl/openssl.cnf 是否存在。如果还是不行,也可以使用交互方式创建 CSR(需要注意 Common Name 必须为你的域名):

1
openssl req -new -sha256 -key domain.key -out domain.csr

配置验证服务

我们知道,CA 在签发 DV(Domain Validation)证书时,需要验证域名所有权。传统 CA 的验证方式一般是往 admin@yoursite.com 发验证邮件,而 Let’s Encrypt 是在你的服务器上生成一个随机验证文件,再通过创建 CSR 时指定的域名访问,如果可以访问则表明你对这个域名有控制权。

首先创建用于存放验证文件的目录,例如:

1
mkdir ~/www/challenges/

然后配置一个 HTTP 服务,以 Nginx 为例:

1
2
3
4
5
6
7
8
9
10
11
12
server {
    server_name www.yoursite.com yoursite.com;

    location ^~ /.well-known/acme-challenge/ {
        alias /home/xxx/www/challenges/;
        try_files $uri =404;
    }

    location / {
        rewrite ^/(.*)$ https://yoursite.com/$1 permanent;
    }
}

以上配置优先查找 ~/www/challenges/ 目录下的文件,如果找不到就重定向到 HTTPS 地址。这个验证服务以后更新证书还要用到,建议一直保留。

获取网站证书

先把 acme-tiny 脚本保存到之前的 ssl 目录:

1
wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py

指定账户私钥、CSR 以及验证目录,执行脚本:

1
python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir ~/www/challenges/ > ./signed.crt

如果一切正常,当前目录下就会生成一个 signed.crt,这就是申请好的证书文件。

如果你把域名 DNS 解析放在国内,这一步很可能会遇到类似这样的错误:

1
ValueError: Wrote file to /home/xxx/www/challenges/oJbvpIhkwkBGBAQUklWJXyC8VbWAdQqlgpwUJkgC1Vg, but couldn't download http://www.yoursite.com/.well-known/acme-challenge/oJbvpIhkwkBGBAQUklWJXyC8VbWAdQqlgpwUJkgC1Vg

这是因为你的域名很可能在国外无法解析,可以找台国外 VPS 验证下。我的域名最近从 DNSPod 换到了阿里云解析,最后又换到了 CloudXNS,就是因为最近前两家在国外都很不稳定。如果你也遇到了类似情况,可以暂时使用国外的 DNS 解析服务商,例如 dns.he.net。如果还是搞不定,也可以试试「Neilpang/le」这个工具的 DNS Mode。

搞定网站证书后,还要下载 Let’s Encrypt 的中间证书。我在之前的文章中讲过,配置 HTTPS 证书时既不要漏掉中间证书,也不要包含根证书。在 Nginx 配置中,需要把中间证书和网站证书合在一起:

1
2
wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > intermediate.pem
cat signed.crt intermediate.pem > chained.pem

为了后续能顺利启用 OCSP Stapling,我们再把根证书和中间证书合在一起:

1
2
wget -O - https://letsencrypt.org/certs/isrgrootx1.pem > root.pem
cat intermediate.pem root.pem > full_chained.pem

最终,修改 Nginx 中有关证书的配置并 reload 服务即可:

1
2
ssl_certificate     ~/www/ssl/chained.pem;
ssl_certificate_key ~/www/ssl/domain.key;

Nginx 中与 HTTPS 有关的配置项很多,这里不一一列举了。如有需要,请参考本站配置

配置自动更新

Let’s Encrypt 签发的证书只有 90 天有效期,推荐使用脚本定期更新。例如我就创建了一个 renew_cert.sh 并通过 chmod a+x renew_cert.sh 赋予执行权限。文件内容如下:

1
2
3
4
5
6
7
#!/bin/bash

cd /home/xxx/www/ssl/
python acme_tiny.py --account-key account.key --csr domain.csr --acme-dir /home/xxx/www/challenges/ > signed.crt || exit
wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > intermediate.pem
cat signed.crt intermediate.pem > chained.pem
service nginx reload

crontab 中使用绝对路径比较保险,crontab -e 加入以下内容:

1
0 0 1 * * /home/xxx/shell/renew_cert.sh >/dev/null 2>&1

这样以后证书每个月都会自动更新,一劳永逸。实际上,Let’s Encrypt 官方将证书有效期定为 90 天一方面是为了更安全,更重要的是鼓励用户采用自动化部署方案。

几个问题

Let’s Encrypt 证书的兼容性,所有操作系统、浏览器默认是否都能识别是大家最关心的问题。实际上,由于 Let’s Encrypt 与 IdenTrust 的 DST Root CA 做了交叉认证,兼容性还是不错的,目前我只是发现在 Android 2 和 Windows XP 下有问题(Firefox 的证书那一套是自己实现的,不依赖于系统,XP 下只有 Firefox 信任 Let’s Encrypt 证书),其它环境都正常。

letsencrypt intermediate cert on winxp(Windows XP 不信任 Let’s Encrypt 的中间证书)

更新:根据 Let’s Encrypt 官方说明,Windows XP 下的问题很快就会解决:

A bug in Windows XP causes parsing of our current cross-signature from IdenTrust to fail. We will be correcting this by getting new cross-signatures from IdenTrust which work on Windows XP.
注:已于 2016 年 3 月 26 日解决。

另外一个问题有关 ECC 证书,官网表示计划将在 2016 年提供对 ECC 证书的支持:

Right now all of our root and intermediate keys use RSA. We’re planning to generate ECC keys and make an ECC option available to subscribers in 2016. via
注:Let’s Encrypt 已于 2016 年 2 月 11 日开始支持签发 ECC 证书。

Let’s Encrypt 官方的新特性预告可以在这个页面查看

我个人建议:对于个人用户来说,如果非常在意证书兼容性,可以购买 RapidSSL Standard 或者 Comodo Positive SSL 这两种证书。其中 RapidSSL 证书一共才三级,比较小;Comodo Positive 有四级,但可以申请 ECC 证书;二者都有着不错的兼容性,也非常廉价(一年不到 10$)。当然,如果不用考虑 Windows XP 用户,那么强烈推荐 Let’s Encrypt!

更新:Let’s Encrypt 已经支持 Windows XP 和签发 ECC 证书,对于个人用户来说,目前 Let’s Encrypt 无疑是最好的选择。

本文先写到这里,如果你在申请 Let’s Encrypt 证书的过程中遇到问题,可以给我留言,也欢迎交流各种心得!

原文链接:https://imququ.com/post/letsencrypt-certificate.html前往原文评论 »

]]>
<![CDATA[[广告]长期收购Paypal零散余额]]> 2018-03-26T19:37:27+08:00 http://antientbook.com/blog/paypal-banlance [广告]长期收购Paypal零散余额

收PayPal美元,兑换成人民币。如果您经常有PayPal美元想兑换成人民币,可以来找我。

交易走闲鱼, 安全有保障。

联系qq: 2753413812 备注来意 否则不添加

over.

]]>
<![CDATA[配置HTTPS证书记录]]> 2018-03-26T19:37:27+08:00 http://antientbook.com/blog/https-ssl 给官网配置HTTPS证书记录,第一次 当然要记录下来, 这是新出炉的官网themis官网

废话不多说,开始正题

1) 弯路

查阅到配置nginx 根证书,和秘钥就可以做到https正常访问

这是老大给我的一窍不通的东西,老大提醒我,要建立证书链,还要注意移动设备访问证书会提示不安全的情况。

1
2
3
4
├── CACertificate-INTERMEDIATE-1.cer
├── CACertificate-ROOT-2.cer
├── themis.key
└── ServerCertificate.cer

当时我还是很懵逼的。所以建议大家还是查询一下证书链。 查阅到如下配置

看看自己的防火墙 终端执行 iptables -L –line-numbers

1
2
3
4
5
6
7
8
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

如上所示没有任何拦截,主要注意443端口拦截

如下配置nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
    listen       443;
    server_name  localhost;
    ssl                  on;
    ssl_certificate      /etc/nginx/sslcer/CACertificate-ROOT-2.cer;
    ssl_certificate_key      /etc/nginx/sslcer/themis.key;
    ssl_session_timeout  5m;
    ssl_protocols  SSLv3 TLSv1;
    ssl_ciphers  HIGH:!ADH:!EXPORT56:RC4+RSA:+MEDIUM;
    ssl_prefer_server_ciphers   on;
    location / {
     root   /data/www/themiswww;
     index  index.html index.htm;
    }
 }

终端执行 nginx -t

1
2
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

这样是秘钥和服务器证书搭配正确 访问 https://themis.im https正常

然后发现移动设备果然提示了 证书不受信任

终端执行 openssl s_client -connect www.themis.im:443

发现提示了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
verify error:num=20:unable to get local issuer certificate
verify return:1
...
verify error:num=27:certificate not trusted
verify return:1
...
verify error:num=21:unable to verify the first certificate
verify return:1
...
Certificate chain
 0 s:/businessCategory=Private.../CN=www.abc.com
   i:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Extended Validation CA - SHA256 - G3
 1 s:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign Extended Validation CA - SHA256 - G2
   i:/OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign

最后的解决方案 生成证书链 终端执行 cat ServerCertificate.cer CACertificate-INTERMEDIATE-1.cer CACertificate-ROOT-2.cer > CACertificate-ROOT-1.pem

把 nginx 配置中的 CACertificate-ROOT-2.cer 替换为CACertificate-ROOT-1.pem

然后再次执行 openssl s_client -connect www.themis.im:443

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Certificate chain
 0 s:/CN=*.themis.im
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=GeoTrust RSA CA 2018
 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=GeoTrust RSA CA 2018
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
 2 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
---
......
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: 512F18AE435BD0A126FE08BA6EC3A1D6343C4A2835B1C6F15B01C5E15B0BBFF0
    Session-ID-ctx:
    Master-Key: F86C0D5F7DF4DC436442CAE41CB6843769089AF5EC025525469ABD0461E612B63F530A55C35AA073EDE9C51BDF97A06D
    Key-Arg   : None
    Start Time: 1522068649
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)

在 myssl做了一下评测

修改了如下配置

1
2
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers  ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4:!DH:!DHE;

over.

]]>
<![CDATA[使用Octopress搭建自己的博客]]> 2018-01-08T19:37:27+08:00 http://antientbook.com/blog/diy 大概每个程序员都想要有一个自己的网站吧,嗯,千里之行,始于足下,不开始永远都只是幻想。

想了很多种博客构成的方式,最后使用了 Octopress,喜欢markdown的方式,嗯,大概就是它了。

废话不多说,开始正题

1) Octopress要求的是Ruby1.9.3,MacOSX自带的Ruby版本是2.x的,所以需要利用一些工具来安装低版本的Ruby。Octopress的官方指南推荐使用的是RVM和rbenv,可以根据需要选择使用需要的工具。

安装rvm

1
$ curl -L https://get.rvm.io | bash -s stable --ruby

使用rvm安装ruby

1
2
3
4
5
$ rvm install ruby-1.9.3-p551 --with-gcc=clang
$ rvm use 1.9.3-p551
$ rvm rubygems latest
$ ruby --version
 #ruby 1.9.3p551 (2014-11-13 revision 48407)

安装Octopress

1
2
3
4
5
6
7
8
9
10
11
#clone octopress
$ git clone git://github.com/imathis/octopress.git octopress
$ cd octopress

#安装依赖
$ gem install bundler
$ rbenv rehash  # 如果你刚才用了rbenv
$ bundle install

#安装octopress默认主题
$ rake install

3) 安装greyshade

1
2
3
4
$ git clone git@github.com:shashankmehta/greyshade.git .themes/greyshade
$ echo "\$greyshade: color;" >> sass/custom/_colors.scss //Substitue 'color' with your highlight color
$ rake "install[greyshade]"
$ rake generate

4)创建和生成博客页面

1
2
3
4
5
# 创建博客
$ rake new_post['title']  #就是在文件夹source/_post下创建title.markdown文件
# 编辑markdown文件
$ rake generate
# 生成博客页面(页面是根据模板生成的,可以按照自己需要更改模板内容)

5)访问它,生成的静态文件在public目录,将nginx的根目录指向它,重启nginx。

]]>