Back

接口的访问基本机制:服务器端的认证 ( web interface basics: server side authentication)

发布时间: 2015-01-03 00:15:00

refer to:  http://nginx.org/en/docs/http/ngx_http_secure_link_module.html
http://www.rackspace.com/blog/add-the-content-md5-http-header-to-nginx/

对于接口的认证,在服务器端的两个地方可以做:

1. nginx , 2. backend (rails, php, .net)等等

在后端做的话,比较耗时。比如: 查询数据库,运行ruby代码,验证是否正确等等。 没有几十毫秒下不来。

而且在 rails/php 等backend, 他们的对并发请求的处理表现是很差劲的。最NB的nodejs 输出 'hello world'也无法过4000.更别提查询数据库了。(一般我看到的是不过50 req/s,每次是1个并发请求)

所以,最好在nginx这一层来做。 快速,而且直接( 要知道nginx对于静态文件的请求速度轻松达到 每秒1000并发,15k个响应)

ngx_http_secure_link_module 分成两种模式:

1. secure_link_secret: 只进行验证 。 

2. secure_link + secure_link_md5: 不但验证,而且还可以检查超时

nginx secure_link 验证的机制:

它只接受两个参数:   secure_link(md5,expiration_time) ,

1. 先验证 md5 对不对。如果不对的话,就认为 $secure_link=''

2. 如果md5 验证通过,但是发现时间已经过期,那么就把 $secure_link = 0

3. 如果md5验证通过,并且时间也正常,那么 $secure_link = 1

如果 expiration_time 设置了,就是 epoch 时间之后的秒数,如果没有设置,就认为它永不过期。

例子:

location /s/ {
    secure_link $arg_md5,$arg_expires;
    secure_link_md5 "$secure_link_expires$uri$remote_addr my_secret";
    if($secure_link=""){
        return 403;   // md5检查未通过
    }
    if($secure_link="0"){
        return 410;   // 过期了
    }
}

那么,这个请求:/s/link?md5=_e4Nc3iduzkWRm01TBBNYw&expires=2147483647 ,就可以看出, md5是由 127.0.0.1 算出来的, secret token = 'my_secret' , 过期时间是 2038年一月19日 

手动生成这个 md5的方式:

echo -n '2147483647/s/link127.0.0.1 secret' | \
    openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d =

nginx secure_link_secret模式验证的机制:

根据指定的md5进行验证,如果通过,则$secure_link 不变,否则, $secure_link="",   例子:

// 验证  /p/a1b2c3d4/interface_name 是否合法
location /p/ {
    secure_link_secret secret;
    if ($secure_link=""){
        return 403;
    }
    rewrite ^ /secure/$secure_link;
}
location /secure/ {
    internal;
}

例如,我们要传递的 link 的全型是:  "/p/5e814704a28d9bc1914ff19fa0c4a00a/link", hacker无法从中获知 客户端的secret, 在server端则可以非常方便的进行识别。

Back