个人笔记

专注互联网

关于盗链

防盗链本质上就是要验证来源,防止对未许可、未授权的请求提供服务,根据验证身份的数据来源可以简单地分为两类

  1. 直接从请求方主动携带的字段中提取,最常用的就是Http 头Referer字段,一些严格的验证包括验证IP地址User Agent等。
  2. 验证信息需要事先从服务端获取或者按照服务端约定的规则提供

Referer

这种方式最流行,最简单,对服务器影响小,一般的cdn(腾讯云,阿里云cdn)都提供Referer防盗链机制,具体可以分为黑名单和白名单,通常支持通配符或者正则表达式,此外一个特例就是是否允许空的Referer。

一般不推荐不允许Referer为空,因为防盗链做得过于严密对于真实用户也是不方便的,比如隐私模式或HTTPS浏览时,就不存在Referer。对于一些特殊资源比如音视频,使用第三方播放器也可能不存在Referer。

常用的后端框架例如JavaSpring,NodeExpress,PythonFlask都可以找到基于Referer的防盗链中间件(过滤器),nginx也有插件http://www.ttlsa.com/nginx/nginx-referer/

破解

要破解首先要明确服务提供方的规则,如果对方允许空Referer,那么将图片dom元素置于frame中即可。一种更好的办法是用服务器中转,在服务器中清掉Referer甚至伪造,但带来额外的服务器开销。

nginx同样可以实现这样的功能

请求方提供授权信息

一般理解,授权就是需要登录的那种,在需要授权的web系统中,可以一并对图片等静态资源作授权(而不仅仅是ajax接口或者web网页路径,虽然静态资源通常不会加入授权访问)。

若只允许资源在本域访问,可以在非资源请求时下发携带授权信息的cookie,而服务器在资源请求中验证cookie,这种方式也很简单,但是若需要授权第三方就比较麻烦。

要实现第三方授权,可以参考跨域cookie共享

这种方案仍然可以用非浏览器的方式获取,

Url Token加超时

若需要授权第三方使用,可以给他提供一个密钥(对称)或者公钥(非对称),在请求我们资源时,url必须携带token和timestamp,token通过url和timestamp加密得来(具体算法呵呵),

根据约定的规则

在我方验证时,需确保token正确,以及时间戳和当前时间戳误差在一定时间内(比方5分钟)。之所以要验证误差,是为了避免因无超时第三方偷懒使用一个固定的地址,而这种固定地址泄漏之后就一直可访问,关于url加密,可以用nginx插件http://www.ttlsa.com/nginx/nginx-modules-secure_link/

自己提供Token

这常见于下载站,请求方需要事先获取一个下载url,这个url同样包含一个token和时间戳,时间戳表示过期时间,这样可以避免url一直可用。

或者简单的,生成一个验证码,并且把验证码放入cookie中,下载时,必须携带这个验证码作为参数,服务器只需要简单的验证cookie中的验证码和参数是否一致,然后删除cookie(使用内存cookie或者超时很短也可以),确保立即失效。

会话

自行/协商生成url 加 超时是个不错的防盗链方法,但有时超时并不一定满足需求,比如专门提供内嵌视频的视频服务提供商,此时商家可能只需要简单地内嵌一个frame网页。

这种情况下,视频的地址仍然是服务提供商动态生成,比如http://video.example.com/a.avi?key=fasdfasd,由于没有超时,这个地址一直可用,为了避免盗链,服务器后端就需要保存会话。

  1. 在第一次访问时,用参数的key作为key,通过Ip,User Agent,Referer等计算value并将键值对存入数据库或者redis中,
  2. 若key存在,就验证value是否匹配

这里的key可以看做跟软件序列号一样,可以通过一个算法批量产生,并且能够自验证有效性。以降低非法key对后端数据库造成的查询压力。

参考

  1. https://blog.goquxiao.com/posts/2015/06/13/fang-dao-lian-zi-liao-zheng-li/
  2. http://oneoo.com/2008/09/03/uri-the-use-of-secret-technology-for-the-key-anti-daolian/
  3. https://onebitbug.me/2013/10/10/use-nginx-lua-module-to-prevent-hotlinking/

关于跨域

说到跨域,做过web开发的都知道怎么回事,本文只是做个笔记总结

常用的几种跨域的方式

jsonp

jsonp解决跨域问题的原理是,浏览器的script标签是不受同源策略限制,你可以在你的网页中设置script的src属性问cdn服务器中静态文件的路径(图片也不受限)。那么就可以使用script标签从服务器获取数据,请求时添加一个参数为callbakc=?,?号时你要执行的回调方法。

服务器返回的数据类似于

callBack({
"param1":true,
"param2":["aa","bb"]
})

本质上就是传入的callback调用需要返回的json参数

不足

  1. 只能用于get方法,无法传递大量数据,或者不适合传输部分数据
  2. 如果出现错误,不会像http请求那样有状态码

ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装。

但是并不能用ajax去发送jsonp的请求,只能用dom操作动态构建dom元素来加载所谓的js。

jsonp虽然就比json多个p,但是并不一定要用json格式的数据作为回调的参数返回

nginx反向代理作中继

既然浏览器禁止ajax的跨域行为,那么可以简单地然nginx在同域做个转发即可解决问题

html5支持的cors

cors本质上就是服务器从头部返回适当的header,告诉浏览器是否允许访问,

浏览器请求

  1. Origin 表示请求来自哪个源
  2. Access-Control-Request-Method 该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法。
  3. Access-Control-Request-Headers 该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段。

服务器响应

  1. Access-Control-Allow-Origin 该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
  2. Access-Control-Allow-Credentials 该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
  3. Access-Control-Expose-Headers 该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader(‘FooBar’)可以返回FooBar字段的值。
  4. Access-Control-Max-Age 该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。
  5. Access-Control-Allow-Methods 该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次”预检”请求。
  6. Access-Control-Allow-Headers 如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在”预检”中请求的字段。

非简单请求 & 预检请求

简单请求的条件如下

(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。预检请求可能包含上述是那种字段,而其他普通请求只需要Origin即可,如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段(详见下文),就知道出错了,从而抛出一个错误.

参考

  1. http://www.ruanyifeng.com/blog/2016/04/cors.html
  2. http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html
  3. http://www.jianshu.com/p/7257e7c60ef5

Redis客户端

redis有官方的客户端redis-cli,使用也很方便,不过有些时候GUI界面的客户端也是不错的选择。关于redis-cli用法,可参考

  1. https://gnuhpc.gitbooks.io/redis-all-about/Operation/redis-cli.html
  2. https://www.kancloud.cn/thinkphp/redis-quickstart/36132
  3. https://maoxian.de/2015/08/1342.html

在Windows下有一个用java写的客户端RedisClient,直接用下面的命令即可运行】

java -jar redisclient-win32.x86.2.0.jar

虽说用java,但是用到了一些Windows特有的库,所以并不支持其他平台使用。

在Linux下,有一个redisdesktop的客户端程序,用QT编写,支持多个平台。本身开源,所以直接build from source。(需要翻墙

# Get source code:
git clone --recursive https://github.com/uglide/RedisDesktopManager.git -b 0.8.0 rdm && cd ./rdm
# ubuntu
cd src/
./configure
source /opt/qt56/bin/qt56-env.sh && qmake && make
# 最终生成的文件路径 bin/linux/release/rdm

# 如果需要安装
sudo make install

也有不少web应用,推荐redis-commander,官方的安装方法很简单

# 安装
$ npm install -g redis-commander
# 运行
$ redis-commander

#
#
king@king:/$ redis-commander --redis-db=1
Using default configuration.
No Save: true
listening on 0.0.0.0 : 8081
Redis Connection localhost:6379 Using Redis DB #0

这种程序较原生客户端体验稍差,默认情况下,用浏览器打开http://127.0.0.1:8081即可访问,这里有个bug,不管指定哪个redisdb,打印的日志和web ui都是db0,但实际数据是对的。

使用jsonschema作参数校验

jsonschema是一个校验库,比如python 版本,也有go 版本。目前前后端分离框架,一般会使用json作为传参的格式,所以用它来作校验也未尝不是一个办法,因为

  1. 规则是标准化的东西,不用去学习一套套的另类规则
  2. 规则可以写到json文件甚至用yaml格式,而不用硬编码到代码中(其他校验方案也有不需要硬编码的)
  3. 在启动时直接cache到内存以提高效率,也可以动态的更新规则
  4. 可以很好地和swagger ui配合使用

为了支持上述论点,基于flasgger开发了项目https://github.com/qjw/flasgger。在前者的基础上做了如下修改

  1. 原版本的flasgger使用yaml来编写文档,本项目改成json格式(因为swagger-ui不认yaml
  2. 完善ref,支持对象定义的相对引用,根目录在配置中指定
  3. 加强校验支持,和swagger使用同一份json定义。增加swag_from注解,提供文档/校验的全局开关和接口独立开关
  4. 支持自定义规则,已规避正则费解和管理的麻烦
  5. 支持自动过滤空置,提高前端开发效率
  6. 自定义错误提示

完整的说明见README

ngrok反向代理局域网开发机

主机和域名

首先需要准备有固定外网IP的主机和域名,假设使用域名test.qiujinwu.com作为提供服务的域名,那么先到dns解析方添加【A记录】,注意包含【test】【*.test】下面是dnspod的记录

对于主机,需要放开一个对内和对外的端口,对内默认是【TCP/4443】,对外根据需要配置,例如微信就必须是http80或者https443。

编译Ngrok

下载代码

git clone https://github.com/inconshreveable/ngrok.git

其他一些地址

git clone https://github.com/tutumcloud/ngrok.git

准备环境

sudo apt-get install build-essential golang mercurial git

需要注意的是,ubuntu14.4默认的golang版本是1.2.1,这会导致下面的错误

ubuntu@VM-61-124-ubuntu:~$ go version
go version go1.2.1 linux/amd64
src/github.com/gorilla/websocket/client.go:361: unknown tls.Config field 'GetCertificate' in struct literal
src/github.com/gorilla/websocket/client.go:370: unknown tls.Config field 'ClientSessionCache' in struct literal
src/github.com/gorilla/websocket/client.go:373: unknown tls.Config field 'CurvePreferences' in struct literal
make: *** [client] Error 2

所以需要将golang升级到1.7。我个人是直接下载【https://storage.googleapis.com/golang/go1.7.linux-amd64.tar.gz】,然后
【tar zxvf go1.7.linux-amd64.tar.gz -C /usr/local】,并且【find /usr -name “go*”】找到匹配的路径,全部都覆盖了一遍。,我在ubuntu 16.04 go版本比较新,没有这些鬼问题。

最终的版本如下

(venv) king@kingqiu:~/proxy/ngrok.bak$ go version
go version go1.7 linux/amd64

编译代码

运行以下命令,注意把域名改掉

openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=test.qiujinwu.com" -days 5000 -out rootCA.pem
openssl genrsa -out device.key 2048
openssl req -new -key device.key -subj "/CN=test.qiujinwu.com" -out device.csr
openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 5000
cp rootCA.pem assets/client/tls/ngrokroot.crt
cp device.crt assets/server/tls/snakeoil.crt
cp device.key assets/server/tls/snakeoil.key

然后(这里必须要sudo,不然某个地方提示没权限)

sudo make release-server release-client

若成功,则会在bin目录下生成客户端和服务端

(venv) king@kingqiu:~/proxy/ngrok$ ls bin/
go-bindata ngrok ngrokd

部署

服务器

将ngrokd拷贝到外网的服务器,运行以下命令

注意domian必须和证书保持完全一致,后面两个端口分别是http、https的端口

sudo ./bin/ngrokd -domain="test.qiujinwu.com" -httpAddr=":80" -httpsAddr=":9082" -tunnelAddr=":4443"

客户端

新建ngrok.cfg作为客户端的配置,用来定义服务器信息

server_addr: test.qiujinwu.com:4443
trust_host_root_certs: false

运行命令

./ngrok -subdomain 【子域名qjw】-proto=http -config=./ngrok.cfg 【端口5000】

这条命令就是把本地的5000端口代理到qjw.test.qiujinwu.com上去了。

特殊场景

考虑一些特殊的需求,例如微信必须要求是80端口,但是服务器已经有其他程序占用了该端口,或者同时运行两个ngrok程序,但又必须分享80端口。这时就需要依赖nginx反向代理来支持

首先,反向代理有一个问题,如下,客户端代理链接包含了ngrok服务器绑定的本地端口(也就是nginx代理到的端口),这时直接访问80端口,ngrok服务器会提示找不到隧道,需要对nginx代理出来的http做一些处理,见下面的分析。

ngrok (Ctrl+C to quit)

Tunnel Status online
Version 1.7/1.7
Forwarding http://qjw.test.qiujinwu.com:8001 -> 127.0.0.1:8188
Web Interface 127.0.0.1:4040
# Conn 0
Avg Conn Time 0.00ms

这种情况下需要在nginx转发配置做一些小改动

upstream ngrok1 {
server 127.0.0.1:8001;
keepalive 64;
}
server {
listen 80;
server_name *.test.qiujinwu.com;
location / {

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host:8001;
proxy_set_header X-Nginx-Proxy true;
proxy_set_header Connection "";
proxy_pass http://ngrok1 ;

}
}
upstream ngrok {
server 127.0.0.1:8002;
keepalive 64;
}
server {
listen 80;
server_name *.test2.qiujinwu.com;
location / {

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host:8002;
proxy_set_header X-Nginx-Proxy true;
proxy_set_header Connection "";
proxy_pass http://ngrok ;

}
}

ngrokd运行,分别通过nginx代理到8001和8002端口,内网机器则通过4443和4444来连接

去除端口

代理到本地之后,http的请求就变成了http://www.domain.com:8002/path#path,为了保持一致,在本地最好用nginx将这个8002去掉

server {
listen 8088;
index index.html;
location / {
#include proxy_params;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:5000;
}
}

#!/bin/bash
{
./ngrokd -domain="test.qiujinwu.com" -httpAddr=":8001" -tunnelAddr=":4443" -httpsAddr=":9082"
}&

{
./ngrokd_qiye -domain="test2.qiujinwu.com" -httpAddr=":8002" -tunnelAddr=":4444" -httpsAddr=":9083"
}&

其他做法

  1. 用docker欺骗ngrok服务器
  2. 若需要代理连个服务,并不需要架设连个ngrok服务,跑两个客户端,配置两个不同的subdomain即可。

参考

  1. https://hocg.in/2016/08/31/Ngrok%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/
  2. https://imququ.com/post/self-hosted-ngrokd.html
  3. https://aotu.io/notes/2016/02/19/ngrok/
  4. https://fengqi.me/unix/409.html
  5. http://blog.csdn.net/xs910115/article/details/50096757

翻墙的一些工具

目前代理shadowsocks客户端连接,后者提供sock5代理,在Windows下可以直接全局代理,Linux比较麻烦。各种平台客户端见https://shadowsocks.org/en/download/clients.html

对于chrome浏览器,可以安装插件switchyomega,以前有个SwitchySharp

SwitchyOmega, 下一代 SwitchySharp 升级版已经完成了。新版完全免费,只希望大家能够继续支持。
P.S. 别担心,更新后可自动升级设置,无须再次手动配置。

firefox可以使用foxyproxy

终端使用代理

proxychains

注意配置中不要画蛇添足,在ProxyList一节中添加sock4

$ apt-get install proxychains

$ cat /etc/proxychains.conf | sed "/^#/d" | sed "/^$/d"
strict_chain
chain_len = 1
proxy_dns
tcp_read_time_out 15000
tcp_connect_time_out 8000
[ProxyList]
socks5 127.0.0.1 1080

使用方法

proxychains curl https://www.twitter.com/
proxychains git push origin master

sock5代理转http代理

$ sudo apt-get install polipo

$ cat /etc/polipo/config | sed "/^#/d" | sed "/^$/d"
logSyslog = true
logFile = /var/log/polipo/polipo.log
proxyAddress = "0.0.0.0"
socksParentProxy = "127.0.0.1:1080"
socksProxyType = socks5
chunkHighMark = 50331648
objectHighMark = 16384
serverMaxSlots = 64
serverSlots = 16
serverSlots1 = 32

$ sudo /etc/init.d/polipo restart
$ export http_proxy="http://127.0.0.1:8123/"

其他

  1. https://www.domecross.com/
  2. https://crola.xyz/
  3. https://shadowsocks.org/en/download/clients.html
  4. https://www.yuntisecure.com/

参考

  1. https://blog.xinshangshangxin.com/2015/06/21/linux%E7%BB%88%E7%AB%AF%E7%BF%BB%E5%A2%99/
  2. https://jingsam.github.io/2016/05/08/setup-shadowsocks-http-proxy-on-ubuntu-server.html

同一台电脑多github帐号的ssh配置

为了免去push时输入密码,用git仓库时,通常都在本地生成ssh密钥对,并且配置到githu,bitbucket、gitlab等平台,例如GitHub创建SSH Keys

ssh-keygen -t rsa -C "youremail@xxx.com"

如果一切顺利,可以在用户目录里找到.ssh目录 里面有id_rsa和id_rsa.pub两个文件。这两个就是SSH Key的秘钥,id_rsa是私钥,id_rsa.pub是公钥。将id_rsa.pub内容拷贝到目标网站的某个地方几个。

多个github帐号不能用同一个key,所以必须创建两个。同样使用上面的命令,不过不能一直回车,存储文件时选择一个不同的路径,仍然确保在.ssh目录下。

新建名为config的文件,内容

Host github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa

Host xxx.github.com
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa1

HostName随意,后续需要用到,所以简单明了会比较好。

如果本地已经有仓库,或者直接clone下来的仓库,需要修改文件.git/config

[remote "origin"]
url = git@xxx.github.com:king/blog.git

或者直接修改remote

git remote rm origin
git remote add origin git@xxx.github.com:king/blog.git

或者clone时使用自定义的地址

git clone git@xxx.github.com:king/blog.git

参考

  1. http://blog.csdn.net/itmyhome1990/article/details/42643233
  2. https://gist.github.com/suziewong/4378434

新博客之旅

选型

之前有个博客用jekyll搞的,但是它依赖ruby,这在Windows下很麻烦,而且ruby个人感觉很另类不喜欢(个人喜好问题),而且编译又慢,所以果断用hexo

安装

安装git,node/npm

创建编写博客的目录,使用npm安装必须的组件

npm install hexo-cli -g
npm install hexo --save
hexo -v
king@king:~/tmp/blog$ hexo -v
hexo: 3.2.2
hexo-cli: 1.0.2
os: Linux 4.4.0-47-generic linux x64
http_parser: 2.5.0
node: 4.2.6
v8: 4.5.103.35
uv: 1.8.0
zlib: 1.2.8
ares: 1.10.1-DEV
icu: 55.1
modules: 46
openssl: 1.0.2g-fips

初始化博客

hexo init
# 安装依赖
npm install
# 编译
hexo g
# 运行
hexo s
king@king:~/tmp/blog$ hexo s
INFO Start processing
INFO Hexo is running at http://localhost:4000/. Press Ctrl+C to stop.

配置

可以在 _config.yml 中修改大部份的配置。

参数 描述
title 网站标题
subtitle 网站副标题
description 网站描述
author 您的名字
参数 描述
theme 当前主题名称。值为false时禁用主题
deploy 部署部分的设置

主题

A simple Bootstrap v3 blog theme for Hexo

https://github.com/cgmartin/hexo-theme-bootstrap-blog

# Extensions
## Plugins: https://hexo.io/plugins/
## Themes: https://hexo.io/themes/
theme: bootstrap-blog

新文章

king@king:~/tmp/blog$ hexo new "start"
INFO Created: ~/tmp/blog/source/_posts/start.md

tag和category

tag支持多个,category支持层级关系

tags:
- hexo
- travis
categories:
- 运营运维
- 网站

域名

新建文件source/CNAME

king@king:~/blog$ cat source/CNAME 
blog.qiujinwu.com

然后在域名管理网站,例如Dnspod,新建CNAME记录。【xxx就是github用户名,注意最后面的点

主机记录 记录类型 记录值
blog CNAME xxx.github.com.

发布

hexo g编译之后,默认会在public目录生成编译好的前端内容,发布可以简单地将这个目录push到github目标仓库的master分支。

# Deployment
## Docs: https://hexo.io/docs/deployment.html
deploy:
type: git
repo: git@github.com:yyy/xxx.git
branch: master

运行下面命令发布

hexo d

发布

前面的发布有个问题,原始文件没有备份。最简单的办法是写个脚本,把源文件和编译好的文件分别push到不同的仓库。若不想别人看到源文件,还可以将源文件的残酷设置为私有(需要掏银子)

另一种办法是将源文件和编译好的文件放在不同的分支,参考Hexo利用Github分支在不同电脑上写博客

另一种办法是用持续集成,推荐travis-ci,参考手把手教你使用Travis CI自动部署你的Hexo博客到Github上

注册github账户,新建两个仓库,一个用于存储博客源文件,一个用于存储编译后的静态内容。对于后者,开启gh-pages功能【注意:只有master分支支持gh-pages功能

用github账户登录travis-ci之后,按照前面参考链接配置好即可,本质上就是push到github的源文件仓库,travis-ci就会收到通知,然后pull下来,并且按照.travis.yml配置的参数执行。

在我的环境下,.travis.yml文件中的命令无法读取到https://travis-ci.org/网站配置的环境变量,所以用另一种加密token的办法实现的,具体参考Hexo 自动部署到 Github

# 安装ruby之后
gem install travis
# cd 博客项目文件夹根目录
travis login --auto
# 加密从github取下来的token,不需要<>
# 此操作会自动往.travis.yml添加一个密钥[env - global - secure]
travis encrypt 'GH_TOKEN=<TOKEN>' --add

完整的文件如下

language: node_js
node_js: stable
install:
- npm install
script:
- hexo g
after_script:
- cd ./public
- git init
- git config user.name "king"
- git config user.email "qiujinwu456@gmail.com"
- git add .
- git commit -m "Update docs"
- git push --force --quiet "https://$GH_TOKEN@${GH_REF}" master:master
branches:
only:
- master
env:
global:
- GH_REF: github.com/xxxx/blog.qiujinwu.com.git
- secure: hmLkN8N2DZ9x/auC9hpdnv/he1XBYtxG/T3z

RSS

参考Hexo—正确添加RSS订阅

# 安装hexo-generator-feed
npm install hexo-generator-feed --save

配置到根目录的_config.yml

plugin:
- hexo-generator-feed
#Feed Atom
feed:
type: atom
path: atom.xml
limit: 20

最后在主题的配置中添加入口

评论

使用disqus

进入disqus网站,填写博客的域名,按照指引完成之后,获取shortname,然后在_config.xml中添加

disqus_shortname: shortname

参考

  1. https://xuanwo.org/2015/03/26/hexo-intor/
  2. http://jiji262.github.io/2016/04/15/2016-04-15-hexo-github-pages-blog/
  3. https://github.com/hexojs/hexo
  4. https://github.com/cgmartin/hexo-theme-bootstrap-blog
  5. http://lotabout.me/2016/Hexo-Auto-Deploy-to-Github